rb125 commited on
Commit
9ee3a0c
·
1 Parent(s): f0fd6e7

added economy coordinator and agent interface

Browse files
Files changed (3) hide show
  1. agents/__init__.py +2 -0
  2. agents/base.py +156 -0
  3. cgae_engine/economy.py +236 -0
agents/__init__.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ """CGAE Agent implementations."""
2
+ from agents.base import BaseAgent, AgentStrategy, AgentDecision
agents/base.py ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Base Agent - Abstract interface for CGAE economic agents.
3
+
4
+ Each agent has:
5
+ - A model identity (simulated or real)
6
+ - A robustness profile (true underlying robustness)
7
+ - An economic strategy (how it decides what to do each step)
8
+ - A wallet (balance, income, expenses)
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import random
14
+ from abc import ABC, abstractmethod
15
+ from dataclasses import dataclass, field
16
+ from enum import Enum
17
+ from typing import Any, Optional
18
+
19
+ from cgae_engine.gate import RobustnessVector, Tier
20
+ from cgae_engine.contracts import CGAEContract
21
+
22
+
23
+ class AgentStrategy(Enum):
24
+ CONSERVATIVE = "conservative"
25
+ AGGRESSIVE = "aggressive"
26
+ BALANCED = "balanced"
27
+ ADAPTIVE = "adaptive"
28
+ CHEATER = "cheater"
29
+
30
+
31
+ @dataclass
32
+ class AgentDecision:
33
+ """What the agent decides to do in a given step."""
34
+ action: str # "bid", "execute", "invest_robustness", "idle", "delegate"
35
+ contract_id: Optional[str] = None
36
+ investment_dimension: Optional[str] = None # "cc", "er", "as"
37
+ investment_amount: float = 0.0
38
+ output: Any = None
39
+ details: dict = field(default_factory=dict)
40
+
41
+
42
+ class BaseAgent(ABC):
43
+ """
44
+ Abstract base class for CGAE economic agents.
45
+
46
+ Subclasses implement the strategy: how the agent decides which contracts
47
+ to bid on, whether to invest in robustness, and how to execute tasks.
48
+ """
49
+
50
+ def __init__(
51
+ self,
52
+ name: str,
53
+ strategy: AgentStrategy,
54
+ true_robustness: RobustnessVector,
55
+ capability: float = 0.5,
56
+ model_config: Optional[dict] = None,
57
+ ):
58
+ self.name = name
59
+ self.strategy = strategy
60
+ self.true_robustness = true_robustness
61
+ self.capability = capability # Task success probability baseline
62
+ self.model_config = model_config or {"model": name, "strategy": strategy.value}
63
+
64
+ # Set by the economy on registration
65
+ self.agent_id: Optional[str] = None
66
+
67
+ # Internal tracking
68
+ self._decisions: list[AgentDecision] = []
69
+ self._step_count: int = 0
70
+
71
+ @abstractmethod
72
+ def decide(
73
+ self,
74
+ available_contracts: list[CGAEContract],
75
+ current_tier: Tier,
76
+ balance: float,
77
+ current_exposure: float,
78
+ budget_ceiling: float,
79
+ ) -> AgentDecision:
80
+ """
81
+ Make a decision for this time step.
82
+
83
+ Args:
84
+ available_contracts: Contracts the agent is eligible to bid on
85
+ current_tier: Agent's current tier
86
+ balance: Current token balance
87
+ current_exposure: Current economic exposure
88
+ budget_ceiling: Maximum exposure for current tier
89
+ """
90
+ ...
91
+
92
+ @abstractmethod
93
+ def execute_task(self, contract: CGAEContract) -> Any:
94
+ """
95
+ Execute a task and produce output.
96
+ The output will be verified against the contract's constraints.
97
+ """
98
+ ...
99
+
100
+ def task_success_probability(self, contract: CGAEContract) -> float:
101
+ """
102
+ Probability of successfully completing a contract.
103
+ Depends on capability and the robustness dimension most
104
+ relevant to the contract.
105
+ """
106
+ base = self.capability
107
+ difficulty = contract.difficulty
108
+ # Higher difficulty reduces success probability
109
+ return max(0.05, min(0.95, base * (1.0 - difficulty * 0.5)))
110
+
111
+ def robustness_investment_cost(self, dimension: str, amount: float) -> float:
112
+ """Cost to improve a robustness dimension by `amount`."""
113
+ # Quadratic cost: harder to improve as you get higher
114
+ current = getattr(self.true_robustness, dimension if dimension != "as" else "as_")
115
+ return amount * (1.0 + current * 2.0)
116
+
117
+ def invest_robustness(self, dimension: str, amount: float) -> RobustnessVector:
118
+ """
119
+ Invest in improving a robustness dimension.
120
+ Returns the new robustness vector.
121
+ """
122
+ cc = self.true_robustness.cc
123
+ er = self.true_robustness.er
124
+ as_ = self.true_robustness.as_
125
+ ih = self.true_robustness.ih
126
+
127
+ if dimension == "cc":
128
+ cc = min(1.0, cc + amount)
129
+ elif dimension == "er":
130
+ er = min(1.0, er + amount)
131
+ elif dimension == "as":
132
+ as_ = min(1.0, as_ + amount)
133
+
134
+ self.true_robustness = RobustnessVector(cc=cc, er=er, as_=as_, ih=ih)
135
+ return self.true_robustness
136
+
137
+ def record_decision(self, decision: AgentDecision):
138
+ self._decisions.append(decision)
139
+ self._step_count += 1
140
+
141
+ @property
142
+ def decisions(self) -> list[AgentDecision]:
143
+ return list(self._decisions)
144
+
145
+ def to_config(self) -> dict:
146
+ return {
147
+ "name": self.name,
148
+ "strategy": self.strategy.value,
149
+ "capability": self.capability,
150
+ "true_robustness": {
151
+ "cc": self.true_robustness.cc,
152
+ "er": self.true_robustness.er,
153
+ "as": self.true_robustness.as_,
154
+ "ih": self.true_robustness.ih,
155
+ },
156
+ }
cgae_engine/economy.py ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CGAE Economy — Top-level coordinator.
3
+
4
+ Ties together registry, gate, contracts, temporal dynamics into
5
+ a single coherent economic system.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ import logging
12
+ import time
13
+ from dataclasses import dataclass, field
14
+ from pathlib import Path
15
+ from typing import Any, Optional
16
+
17
+ from cgae_engine.gate import GateFunction, RobustnessVector, Tier, TierThresholds
18
+ from cgae_engine.temporal import TemporalDecay, StochasticAuditor
19
+ from cgae_engine.registry import AgentRegistry, AgentRecord, AgentStatus
20
+ from cgae_engine.contracts import ContractManager, CGAEContract, ContractStatus, Constraint
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ @dataclass
26
+ class EconomyConfig:
27
+ """Configuration for the CGAE economy."""
28
+ thresholds: TierThresholds = field(default_factory=TierThresholds)
29
+ decay_rate: float = 0.01
30
+ ih_threshold: float = 0.45
31
+ initial_balance: float = 0.1
32
+ audit_cost: float = 0.005
33
+ storage_cost_per_step: float = 0.001
34
+
35
+
36
+ class Economy:
37
+ """
38
+ The CGAE Economy runtime.
39
+
40
+ Orchestrates:
41
+ 1. Agent registration and initial audit
42
+ 2. Contract creation and marketplace
43
+ 3. Contract assignment (tier-gated)
44
+ 4. Task execution and verification
45
+ 5. Settlement (reward/penalty)
46
+ 6. Temporal decay and stochastic re-auditing
47
+ """
48
+
49
+ def __init__(self, config: Optional[EconomyConfig] = None):
50
+ self.config = config or EconomyConfig()
51
+ self.gate = GateFunction(
52
+ thresholds=self.config.thresholds,
53
+ ih_threshold=self.config.ih_threshold,
54
+ )
55
+ self.registry = AgentRegistry(gate=self.gate)
56
+ self.contracts = ContractManager(budget_ceilings=self.gate.budget_ceilings)
57
+ self.decay = TemporalDecay(decay_rate=self.config.decay_rate)
58
+ self.auditor = StochasticAuditor()
59
+
60
+ self.current_time: float = 0.0
61
+ self._events: list[dict] = []
62
+
63
+ # ------------------------------------------------------------------
64
+ # Agent lifecycle
65
+ # ------------------------------------------------------------------
66
+
67
+ def register_agent(
68
+ self,
69
+ model_name: str,
70
+ model_config: dict,
71
+ provenance: Optional[dict] = None,
72
+ ) -> AgentRecord:
73
+ """Register a new agent with seed capital."""
74
+ record = self.registry.register(
75
+ model_name=model_name,
76
+ model_config=model_config,
77
+ provenance=provenance,
78
+ initial_balance=self.config.initial_balance,
79
+ timestamp=self.current_time,
80
+ )
81
+ self._log("agent_registered", {"agent_id": record.agent_id, "model": model_name})
82
+ return record
83
+
84
+ def audit_agent(
85
+ self,
86
+ agent_id: str,
87
+ robustness: RobustnessVector,
88
+ audit_type: str = "registration",
89
+ audit_details: Optional[dict] = None,
90
+ ) -> dict:
91
+ """Audit an agent and update their certification."""
92
+ record = self.registry.get_agent(agent_id)
93
+ if record is None:
94
+ raise KeyError(f"Agent {agent_id} not found")
95
+
96
+ total_audit_cost = self.config.audit_cost * 4
97
+ record.balance -= total_audit_cost
98
+ record.total_spent += total_audit_cost
99
+
100
+ cert = self.registry.certify(
101
+ agent_id=agent_id,
102
+ robustness=robustness,
103
+ audit_type=audit_type,
104
+ timestamp=self.current_time,
105
+ audit_details=audit_details,
106
+ )
107
+
108
+ detail = self.gate.evaluate_with_detail(robustness)
109
+ self._log("agent_audited", {
110
+ "agent_id": agent_id,
111
+ "tier": cert.tier.name,
112
+ "audit_type": audit_type,
113
+ "cost": total_audit_cost,
114
+ **detail,
115
+ })
116
+ return detail
117
+
118
+ # ------------------------------------------------------------------
119
+ # Contract lifecycle
120
+ # ------------------------------------------------------------------
121
+
122
+ def post_contract(
123
+ self,
124
+ objective: str,
125
+ constraints: list[Constraint],
126
+ min_tier: Tier,
127
+ reward: float,
128
+ penalty: float,
129
+ deadline_offset: float = 100.0,
130
+ domain: str = "general",
131
+ difficulty: float = 0.5,
132
+ issuer_id: str = "system",
133
+ ) -> CGAEContract:
134
+ """Post a new contract to the marketplace."""
135
+ return self.contracts.create_contract(
136
+ objective=objective,
137
+ constraints=constraints,
138
+ min_tier=min_tier,
139
+ reward=reward,
140
+ penalty=penalty,
141
+ issuer_id=issuer_id,
142
+ deadline=self.current_time + deadline_offset,
143
+ domain=domain,
144
+ difficulty=difficulty,
145
+ timestamp=self.current_time,
146
+ )
147
+
148
+ def accept_contract(self, contract_id: str, agent_id: str) -> bool:
149
+ """Agent accepts a contract. Enforces tier and budget ceiling."""
150
+ record = self.registry.get_agent(agent_id)
151
+ if record is None or record.status != AgentStatus.ACTIVE:
152
+ return False
153
+ if record.current_certification is None:
154
+ return False
155
+
156
+ dt = self.current_time - record.current_certification.timestamp
157
+ r_eff = self.decay.effective_robustness(record.current_robustness, dt)
158
+ effective_tier = self.gate.evaluate(r_eff)
159
+
160
+ return self.contracts.assign_contract(
161
+ contract_id=contract_id,
162
+ agent_id=agent_id,
163
+ agent_tier=effective_tier,
164
+ timestamp=self.current_time,
165
+ )
166
+
167
+ def complete_contract(
168
+ self,
169
+ contract_id: str,
170
+ output: Any,
171
+ ) -> dict:
172
+ """Submit output for a contract and settle it."""
173
+ passed, failures = self.contracts.submit_output(
174
+ contract_id=contract_id,
175
+ output=output,
176
+ timestamp=self.current_time,
177
+ )
178
+
179
+ settlement = self.contracts.settle_contract(
180
+ contract_id=contract_id,
181
+ timestamp=self.current_time,
182
+ )
183
+
184
+ agent_id = settlement["agent_id"]
185
+ performer = self.registry.get_agent(agent_id)
186
+
187
+ if settlement["outcome"] == "success":
188
+ if performer:
189
+ performer.balance += settlement["reward"]
190
+ performer.total_earned += settlement["reward"]
191
+ performer.contracts_completed += 1
192
+ else:
193
+ if performer:
194
+ performer.balance -= settlement["penalty"]
195
+ performer.total_penalties += settlement["penalty"]
196
+ performer.contracts_failed += 1
197
+
198
+ settlement["failures"] = failures
199
+ self._log("contract_settled", settlement)
200
+ return settlement
201
+
202
+ # ------------------------------------------------------------------
203
+ # Observability
204
+ # ------------------------------------------------------------------
205
+
206
+ def aggregate_safety(self) -> float:
207
+ """Compute aggregate safety S(P) (Definition 9)."""
208
+ total_exposure = 0.0
209
+ weighted_risk = 0.0
210
+
211
+ for agent in self.registry.active_agents:
212
+ cert = agent.current_certification
213
+ if cert is None:
214
+ continue
215
+ dt = self.current_time - cert.timestamp
216
+ r_eff = self.decay.effective_robustness(cert.robustness, dt)
217
+ exposure = self.contracts.agent_exposure(agent.agent_id)
218
+ if exposure <= 0:
219
+ tier = self.gate.evaluate(r_eff)
220
+ exposure = self.gate.budget_ceiling(tier)
221
+
222
+ r_bar = r_eff.weakest
223
+ total_exposure += exposure
224
+ weighted_risk += exposure * (1.0 - r_bar)
225
+
226
+ if total_exposure == 0:
227
+ return 1.0
228
+ return 1.0 - (weighted_risk / total_exposure)
229
+
230
+ def _log(self, event_type: str, data: dict):
231
+ self._events.append({
232
+ "type": event_type,
233
+ "timestamp": self.current_time,
234
+ "data": data,
235
+ })
236
+ logger.debug(f"[t={self.current_time:.1f}] {event_type}: {data}")