agentic-settle 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,65 @@
1
+ """
2
+ AgenticSettle SDK
3
+ =================
4
+
5
+ A thin client for the AgenticSettle Pro settlement engine.
6
+
7
+ V1 quickstart (legacy sync settlement)::
8
+
9
+ from agentic_settle import SettleClient
10
+
11
+ client = SettleClient(
12
+ base_url="https://api.agenticsettle.io",
13
+ api_key="...",
14
+ )
15
+ receipt = client.settle(
16
+ agent_id="gpt-4o",
17
+ request_content="prompt...",
18
+ result_content="answer...",
19
+ target_wallet="0x...",
20
+ )
21
+ print(receipt.status, receipt.chain_tx_hash)
22
+
23
+ V2 quickstart (prepaid-token + verification-gated)::
24
+
25
+ client.register_agent("acme-ai")
26
+ client.register_token("ACME-CREDIT", "acme-ai")
27
+ client.purchase_tokens(customer_id="cust_42", token_id="ACME-CREDIT", amount=1000)
28
+
29
+ task = client.create_task(
30
+ customer_id="cust_42", agent_id="acme-ai", token_id="ACME-CREDIT",
31
+ escrow_amount=100, request_content="Summarize this 80-page PDF",
32
+ )
33
+ delivered = client.deliver(task.task_id, result_content=agent_result)
34
+ if delivered.verdict["verdict"] == "PASS":
35
+ client.decide(task.task_id, "SATISFIED")
36
+ else:
37
+ client.decide(task.task_id, "UNSATISFIED", reason="섹션 2 누락")
38
+ """
39
+
40
+ from .client import AsyncSettleClient, SettleClient
41
+ from .types import (
42
+ DecisionResult,
43
+ DeliveryResult,
44
+ SettleReceipt,
45
+ SettleRequest,
46
+ TaskOrder,
47
+ TokenBalance,
48
+ VerificationReport,
49
+ )
50
+
51
+ __all__ = [
52
+ # V1
53
+ "SettleClient",
54
+ "AsyncSettleClient",
55
+ "SettleRequest",
56
+ "SettleReceipt",
57
+ # V2
58
+ "TokenBalance",
59
+ "TaskOrder",
60
+ "VerificationReport",
61
+ "DeliveryResult",
62
+ "DecisionResult",
63
+ ]
64
+
65
+ __version__ = "0.2.0"
@@ -0,0 +1,434 @@
1
+ """
2
+ HTTP clients for the AgenticSettle settlement engine.
3
+
4
+
5
+ - ``SettleClient`` — synchronous (requests-free; uses ``httpx``)
6
+ - ``AsyncSettleClient`` — asyncio-friendly variant for high-throughput agents
7
+
8
+ Both share identical surface area; pick whichever fits your runtime.
9
+
10
+ V1 helpers (`settle`, `get_status`, `dashboard_metrics`) are unchanged.
11
+ V2 helpers cover the new prepaid-token + verification-gated flow.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import os
17
+ import uuid
18
+ from typing import Any
19
+
20
+ import httpx
21
+
22
+ from .types import (
23
+ DecisionResult,
24
+ DeliveryResult,
25
+ SettleReceipt,
26
+ SettleRequest,
27
+ TaskOrder,
28
+ TokenBalance,
29
+ VerificationReport,
30
+ )
31
+
32
+ _DEFAULT_TIMEOUT = 30.0
33
+ _SDK_VERSION = "0.2.0"
34
+
35
+
36
+ def _gen_request_id() -> str:
37
+ return f"REQ-{uuid.uuid4().hex[:12].upper()}"
38
+
39
+
40
+ def _gen_task_id() -> str:
41
+ return f"TSK-{uuid.uuid4().hex[:12].upper()}"
42
+
43
+
44
+ def _headers(api_key: str) -> dict[str, str]:
45
+ return {
46
+ "x-api-key": api_key,
47
+ "content-type": "application/json",
48
+ "user-agent": f"agentic-settle-sdk/{_SDK_VERSION}",
49
+ }
50
+
51
+
52
+ class _Base:
53
+ def __init__(
54
+ self,
55
+ base_url: str | None = None,
56
+ api_key: str | None = None,
57
+ timeout: float = _DEFAULT_TIMEOUT,
58
+ ) -> None:
59
+ self.base_url = (
60
+ base_url or os.getenv("AGENTIC_SETTLE_BASE_URL", "http://localhost:8000")
61
+ ).rstrip("/")
62
+ self.api_key = (
63
+ api_key
64
+ or os.getenv("AGENTIC_SETTLE_API_KEY")
65
+ or os.getenv("BRUCE_SECRET_KEY")
66
+ )
67
+ if not self.api_key:
68
+ raise ValueError(
69
+ "AgenticSettle SDK: no API key. "
70
+ "Pass api_key=... or set AGENTIC_SETTLE_API_KEY in the environment."
71
+ )
72
+ self.timeout = timeout
73
+
74
+ def _build_payload(
75
+ self,
76
+ *,
77
+ agent_id: str,
78
+ request_content: str,
79
+ result_content: str,
80
+ target_wallet: str,
81
+ request_id: str | None,
82
+ ) -> dict[str, Any]:
83
+ req = SettleRequest(
84
+ request_id=request_id or _gen_request_id(),
85
+ agent_id=agent_id,
86
+ request_content=request_content,
87
+ result_content=result_content,
88
+ target_wallet=target_wallet,
89
+ )
90
+ return req.model_dump()
91
+
92
+
93
+ # ─────────────────────────────────────────────────────────────────────────
94
+ # Sync client
95
+ # ─────────────────────────────────────────────────────────────────────────
96
+ class SettleClient(_Base):
97
+ """Synchronous client (V1 + V2)."""
98
+
99
+ # ── V1 (unchanged) ──────────────────────────────────────────────
100
+ def settle(
101
+ self,
102
+ *,
103
+ agent_id: str,
104
+ request_content: str,
105
+ result_content: str,
106
+ target_wallet: str,
107
+ request_id: str | None = None,
108
+ ) -> SettleReceipt:
109
+ payload = self._build_payload(
110
+ agent_id=agent_id,
111
+ request_content=request_content,
112
+ result_content=result_content,
113
+ target_wallet=target_wallet,
114
+ request_id=request_id,
115
+ )
116
+ with httpx.Client(timeout=self.timeout) as c:
117
+ r = c.post(f"{self.base_url}/v1/settle", json=payload, headers=_headers(self.api_key))
118
+ r.raise_for_status()
119
+ return SettleReceipt.model_validate(r.json())
120
+
121
+ def get_status(self, request_id: str) -> SettleReceipt:
122
+ with httpx.Client(timeout=self.timeout) as c:
123
+ r = c.get(
124
+ f"{self.base_url}/v1/settle/status/{request_id}",
125
+ headers=_headers(self.api_key),
126
+ )
127
+ r.raise_for_status()
128
+ return SettleReceipt.model_validate(r.json())
129
+
130
+ def dashboard_metrics(self) -> dict[str, Any]:
131
+ with httpx.Client(timeout=self.timeout) as c:
132
+ r = c.get(
133
+ f"{self.base_url}/v1/settle/dashboard-metrics",
134
+ headers=_headers(self.api_key),
135
+ )
136
+ r.raise_for_status()
137
+ return r.json()
138
+
139
+ # ── V2: prepaid-token + verification-gated flow ────────────────
140
+ def register_agent(
141
+ self, agent_id: str, *, company_name: str | None = None,
142
+ payout_wallet: str | None = None,
143
+ ) -> dict[str, Any]:
144
+ return self._post("/v2/agents/register", {
145
+ "agent_id": agent_id,
146
+ "company_name": company_name,
147
+ "payout_wallet": payout_wallet,
148
+ })
149
+
150
+ def register_token(
151
+ self, token_id: str, agent_id: str, *, symbol: str | None = None,
152
+ decimals: int = 0, unit_price_wei: str | None = None,
153
+ erc20_address: str | None = None,
154
+ ) -> dict[str, Any]:
155
+ return self._post("/v2/tokens/register", {
156
+ "token_id": token_id,
157
+ "agent_id": agent_id,
158
+ "symbol": symbol,
159
+ "decimals": decimals,
160
+ "unit_price_wei": unit_price_wei,
161
+ "erc20_address": erc20_address,
162
+ })
163
+
164
+ def purchase_tokens(
165
+ self, *, customer_id: str, token_id: str, amount: int,
166
+ paid_wei: str | None = None, paid_method: str = "OFFCHAIN",
167
+ tx_ref: str | None = None,
168
+ ) -> dict[str, Any]:
169
+ return self._post("/v2/tokens/purchase", {
170
+ "customer_id": customer_id,
171
+ "token_id": token_id,
172
+ "amount": amount,
173
+ "paid_wei": paid_wei,
174
+ "paid_method": paid_method,
175
+ "tx_ref": tx_ref,
176
+ })
177
+
178
+ def get_balance(self, customer_id: str, token_id: str) -> TokenBalance:
179
+ return TokenBalance.model_validate(self._get(
180
+ "/v2/tokens/balance",
181
+ params={"customer_id": customer_id, "token_id": token_id},
182
+ ))
183
+
184
+ def create_task(
185
+ self, *, customer_id: str, agent_id: str, token_id: str,
186
+ escrow_amount: int, request_content: str,
187
+ task_id: str | None = None, max_rework: int | None = None,
188
+ ) -> TaskOrder:
189
+ body = {
190
+ "task_id": task_id or _gen_task_id(),
191
+ "customer_id": customer_id,
192
+ "agent_id": agent_id,
193
+ "token_id": token_id,
194
+ "escrow_amount": escrow_amount,
195
+ "request_content": request_content,
196
+ "max_rework": max_rework,
197
+ }
198
+ return TaskOrder.model_validate(self._post("/v2/tasks", body))
199
+
200
+ def deliver(
201
+ self, task_id: str, *, result_content: str,
202
+ result_uri: str | None = None,
203
+ ) -> DeliveryResult:
204
+ return DeliveryResult.model_validate(self._post(
205
+ f"/v2/tasks/{task_id}/deliver",
206
+ {"result_content": result_content, "result_uri": result_uri},
207
+ ))
208
+
209
+ def decide(
210
+ self, task_id: str, decision: str, *, reason: str | None = None,
211
+ ) -> DecisionResult:
212
+ return DecisionResult.model_validate(self._post(
213
+ f"/v2/tasks/{task_id}/decide",
214
+ {"decision": decision, "reason": reason},
215
+ ))
216
+
217
+ def dispute(self, task_id: str, *, reason: str | None = None) -> TaskOrder:
218
+ return TaskOrder.model_validate(self._post(
219
+ f"/v2/tasks/{task_id}/dispute", {"reason": reason}
220
+ ))
221
+
222
+ def get_task(self, task_id: str) -> TaskOrder:
223
+ return TaskOrder.model_validate(self._get(f"/v2/tasks/{task_id}"))
224
+
225
+ def get_reports(self, task_id: str) -> list[VerificationReport]:
226
+ raw = self._get(f"/v2/tasks/{task_id}/report")
227
+ return [VerificationReport.model_validate(r) for r in raw.get("reports", [])]
228
+
229
+ def v2_metrics(self) -> dict[str, Any]:
230
+ return self._get("/v2/metrics")
231
+
232
+ # ── V2 verify-only (field-test, PIVOT_V2.md §14) ─────────────────
233
+ def verify(
234
+ self,
235
+ *,
236
+ request_content: str,
237
+ result_content: str,
238
+ agent_id: str | None = None,
239
+ customer_label: str | None = None,
240
+ title: str | None = None,
241
+ sla: dict | None = None,
242
+ work_seconds: int | None = None,
243
+ sla_seconds: int | None = None,
244
+ audience: str = "customer",
245
+ verification_id: str | None = None,
246
+ ) -> dict[str, Any]:
247
+ """One-shot quality verification with no escrow / settlement."""
248
+ return self._post("/v2/verify", {
249
+ "verification_id": verification_id,
250
+ "agent_id": agent_id,
251
+ "customer_label": customer_label,
252
+ "title": title,
253
+ "request_content": request_content,
254
+ "result_content": result_content,
255
+ "sla": sla,
256
+ "work_seconds": work_seconds,
257
+ "sla_seconds": sla_seconds,
258
+ "audience": audience,
259
+ })
260
+
261
+ def get_verification(
262
+ self, verification_id: str, *, audience: str = "customer"
263
+ ) -> dict[str, Any]:
264
+ return self._get(
265
+ f"/v2/verifications/{verification_id}",
266
+ params={"audience": audience},
267
+ )
268
+
269
+ def agent_performance(self, agent_id: str) -> dict[str, Any]:
270
+ return self._get(f"/v2/agents/{agent_id}/performance")
271
+
272
+ # ── V2.1.C — Agent credits (AC) ──────────────────────────────────
273
+ def agent_credits(self, agent_id: str) -> dict[str, Any]:
274
+ """Read the agent's accrued AgentCredit balance."""
275
+ return self._get(f"/v2/agents/{agent_id}/credits")
276
+
277
+ def convert_agent_credits(
278
+ self, agent_id: str, *, amount_ac: int, ref: str | None = None,
279
+ ) -> dict[str, Any]:
280
+ """Burn ``amount_ac`` AC → record VOP-conversion event."""
281
+ return self._post(
282
+ f"/v2/agents/{agent_id}/credits/convert",
283
+ {"amount_ac": amount_ac, "ref": ref},
284
+ )
285
+
286
+
287
+
288
+ # ── Tiny transport helpers ─────────────────────────────────────
289
+ def _post(self, path: str, body: dict[str, Any]) -> dict[str, Any]:
290
+ with httpx.Client(timeout=self.timeout) as c:
291
+ r = c.post(f"{self.base_url}{path}", json=body, headers=_headers(self.api_key))
292
+ r.raise_for_status()
293
+ return r.json()
294
+
295
+ def _get(
296
+ self, path: str, *, params: dict[str, Any] | None = None,
297
+ ) -> dict[str, Any]:
298
+ with httpx.Client(timeout=self.timeout) as c:
299
+ r = c.get(
300
+ f"{self.base_url}{path}", params=params,
301
+ headers=_headers(self.api_key),
302
+ )
303
+ r.raise_for_status()
304
+ return r.json()
305
+
306
+
307
+ # ─────────────────────────────────────────────────────────────────────────
308
+ # Async client
309
+ # ─────────────────────────────────────────────────────────────────────────
310
+ class AsyncSettleClient(_Base):
311
+ """Asyncio variant — recommended for high-throughput agent runtimes."""
312
+
313
+ # ── V1 (unchanged) ─────────────────────────────────────────────
314
+ async def settle(
315
+ self,
316
+ *,
317
+ agent_id: str,
318
+ request_content: str,
319
+ result_content: str,
320
+ target_wallet: str,
321
+ request_id: str | None = None,
322
+ ) -> SettleReceipt:
323
+ payload = self._build_payload(
324
+ agent_id=agent_id,
325
+ request_content=request_content,
326
+ result_content=result_content,
327
+ target_wallet=target_wallet,
328
+ request_id=request_id,
329
+ )
330
+ async with httpx.AsyncClient(timeout=self.timeout) as c:
331
+ r = await c.post(
332
+ f"{self.base_url}/v1/settle",
333
+ json=payload,
334
+ headers=_headers(self.api_key),
335
+ )
336
+ r.raise_for_status()
337
+ return SettleReceipt.model_validate(r.json())
338
+
339
+ async def get_status(self, request_id: str) -> SettleReceipt:
340
+ async with httpx.AsyncClient(timeout=self.timeout) as c:
341
+ r = await c.get(
342
+ f"{self.base_url}/v1/settle/status/{request_id}",
343
+ headers=_headers(self.api_key),
344
+ )
345
+ r.raise_for_status()
346
+ return SettleReceipt.model_validate(r.json())
347
+
348
+ async def dashboard_metrics(self) -> dict[str, Any]:
349
+ async with httpx.AsyncClient(timeout=self.timeout) as c:
350
+ r = await c.get(
351
+ f"{self.base_url}/v1/settle/dashboard-metrics",
352
+ headers=_headers(self.api_key),
353
+ )
354
+ r.raise_for_status()
355
+ return r.json()
356
+
357
+ # ── V2 (async mirrors of the sync API) ─────────────────────────
358
+ async def purchase_tokens(
359
+ self, *, customer_id: str, token_id: str, amount: int,
360
+ paid_wei: str | None = None, paid_method: str = "OFFCHAIN",
361
+ tx_ref: str | None = None,
362
+ ) -> dict[str, Any]:
363
+ return await self._apost("/v2/tokens/purchase", {
364
+ "customer_id": customer_id,
365
+ "token_id": token_id,
366
+ "amount": amount,
367
+ "paid_wei": paid_wei,
368
+ "paid_method": paid_method,
369
+ "tx_ref": tx_ref,
370
+ })
371
+
372
+ async def get_balance(self, customer_id: str, token_id: str) -> TokenBalance:
373
+ return TokenBalance.model_validate(await self._aget(
374
+ "/v2/tokens/balance",
375
+ params={"customer_id": customer_id, "token_id": token_id},
376
+ ))
377
+
378
+ async def create_task(
379
+ self, *, customer_id: str, agent_id: str, token_id: str,
380
+ escrow_amount: int, request_content: str,
381
+ task_id: str | None = None, max_rework: int | None = None,
382
+ ) -> TaskOrder:
383
+ body = {
384
+ "task_id": task_id or _gen_task_id(),
385
+ "customer_id": customer_id,
386
+ "agent_id": agent_id,
387
+ "token_id": token_id,
388
+ "escrow_amount": escrow_amount,
389
+ "request_content": request_content,
390
+ "max_rework": max_rework,
391
+ }
392
+ return TaskOrder.model_validate(await self._apost("/v2/tasks", body))
393
+
394
+ async def deliver(
395
+ self, task_id: str, *, result_content: str,
396
+ result_uri: str | None = None,
397
+ ) -> DeliveryResult:
398
+ return DeliveryResult.model_validate(await self._apost(
399
+ f"/v2/tasks/{task_id}/deliver",
400
+ {"result_content": result_content, "result_uri": result_uri},
401
+ ))
402
+
403
+ async def decide(
404
+ self, task_id: str, decision: str, *, reason: str | None = None,
405
+ ) -> DecisionResult:
406
+ return DecisionResult.model_validate(await self._apost(
407
+ f"/v2/tasks/{task_id}/decide",
408
+ {"decision": decision, "reason": reason},
409
+ ))
410
+
411
+ async def get_reports(self, task_id: str) -> list[VerificationReport]:
412
+ raw = await self._aget(f"/v2/tasks/{task_id}/report")
413
+ return [VerificationReport.model_validate(r) for r in raw.get("reports", [])]
414
+
415
+ # ── Transport ──────────────────────────────────────────────────
416
+ async def _apost(self, path: str, body: dict[str, Any]) -> dict[str, Any]:
417
+ async with httpx.AsyncClient(timeout=self.timeout) as c:
418
+ r = await c.post(
419
+ f"{self.base_url}{path}", json=body,
420
+ headers=_headers(self.api_key),
421
+ )
422
+ r.raise_for_status()
423
+ return r.json()
424
+
425
+ async def _aget(
426
+ self, path: str, *, params: dict[str, Any] | None = None,
427
+ ) -> dict[str, Any]:
428
+ async with httpx.AsyncClient(timeout=self.timeout) as c:
429
+ r = await c.get(
430
+ f"{self.base_url}{path}", params=params,
431
+ headers=_headers(self.api_key),
432
+ )
433
+ r.raise_for_status()
434
+ return r.json()
File without changes
@@ -0,0 +1,98 @@
1
+ """
2
+ Public data types exposed by the SDK.
3
+
4
+ Kept intentionally framework-agnostic (pydantic v2 dataclasses) so SDK users
5
+ don't have to install FastAPI / SQLite / web3 to call the API.
6
+
7
+ V1 types are retained verbatim. V2 types implement the prepaid-token +
8
+ verification-gated settlement flow (see ``PIVOT_V2.md``).
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from pydantic import BaseModel, Field
14
+
15
+
16
+ # ─────────────────────────────────────────────────────────────────────────
17
+ # V1 — legacy settle endpoint (kept for backward compatibility)
18
+ # ─────────────────────────────────────────────────────────────────────────
19
+ class SettleRequest(BaseModel):
20
+ """Payload posted to ``POST /v1/settle``."""
21
+
22
+ request_id: str = Field(..., description="Caller-generated idempotency key.")
23
+ agent_id: str = Field(..., description="Logical agent identifier, e.g. 'gpt-4o'.")
24
+ request_content: str = Field(..., description="Original user prompt / task input.")
25
+ result_content: str = Field(..., description="Agent's produced result to be scored.")
26
+ target_wallet: str = Field(..., description="Recipient EOA for the on-chain payout.")
27
+
28
+
29
+ class SettleReceipt(BaseModel):
30
+ """Response returned by the settlement engine."""
31
+
32
+ request_id: str
33
+ status: str = Field(..., description="One of PENDING / COMPLETED / GAS_HOLD / DISPUTED / SLASHED.")
34
+ score: int | None = None
35
+ tier: str | None = None
36
+ payout_eth: float | None = None
37
+ gas_saved_gwei: int | None = None
38
+ chain_tx_hash: str | None = None
39
+ receipt: str | None = Field(None, description="Signed receipt blob (HMAC).")
40
+ timestamp: str | None = None
41
+
42
+
43
+ # ─────────────────────────────────────────────────────────────────────────
44
+ # V2 — prepaid-token + verification-gated settlement
45
+ # ─────────────────────────────────────────────────────────────────────────
46
+ class TokenBalance(BaseModel):
47
+ """Customer × agent-token balance snapshot."""
48
+
49
+ customer_id: str
50
+ token_id: str
51
+ balance: int = Field(..., description="Total credited tokens.")
52
+ locked: int = Field(0, description="Currently held in escrow.")
53
+ available: int = Field(..., description="balance - locked")
54
+
55
+
56
+ class TaskOrder(BaseModel):
57
+ """Task created against an escrowed bag of tokens (``POST /v2/tasks``)."""
58
+
59
+ task_id: str
60
+ customer_id: str
61
+ agent_id: str
62
+ token_id: str
63
+ escrow_amount: int = Field(..., gt=0)
64
+ request_content: str = ""
65
+ status: str | None = None
66
+ rework_count: int = 0
67
+ max_rework: int | None = None
68
+
69
+
70
+ class VerificationReport(BaseModel):
71
+ """One round of VOP verification (``GET /v2/tasks/{id}/report``)."""
72
+
73
+ report_id: str
74
+ round_no: int
75
+ vop_score: int
76
+ tier: str | None = None
77
+ verdict: str = Field(..., description="PASS | FAIL")
78
+ fail_codes: list[str] = Field(default_factory=list)
79
+ onchain_tx_hash: str | None = None
80
+ issued_at: str | None = None
81
+
82
+
83
+ class DeliveryResult(BaseModel):
84
+ """Response from ``POST /v2/tasks/{id}/deliver``."""
85
+
86
+ delivery_id: str
87
+ round_no: int
88
+ report_id: str
89
+ verdict: dict
90
+ task: dict
91
+
92
+
93
+ class DecisionResult(BaseModel):
94
+ """Response from ``POST /v2/tasks/{id}/decide``."""
95
+
96
+ decision_id: str
97
+ task: dict
98
+ charge_id: str | None = None
@@ -0,0 +1,99 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentic-settle
3
+ Version: 0.2.0
4
+ Summary: Python SDK for AgenticSettle — verify any AI agent's output, settle with pre-paid token escrow, earn the Verified badge.
5
+ Author-email: "AgenticSettle.IO" <engineering@agenticsettle.io>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/agenticsettleio/agentic-settle-core
8
+ Project-URL: Issues, https://github.com/agenticsettleio/agentic-settle-core/issues
9
+ Keywords: agentic,settlement,web3,kms,fastapi,sdk
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: httpx>=0.27.0
23
+ Requires-Dist: pydantic>=2.0.0
24
+ Dynamic: license-file
25
+
26
+ # agentic-settle
27
+
28
+ Python client SDK for the **AgenticSettle Pro** settlement engine.
29
+
30
+ A deliberately thin wrapper over the REST API so AI-native applications can
31
+ spend less than 30 seconds wiring up on-chain settlement for their agents.
32
+
33
+ ```bash
34
+ pip install agentic-settle
35
+ ```
36
+
37
+ ## Quickstart (synchronous)
38
+
39
+ ```python
40
+ import os
41
+ from agentic_settle import SettleClient
42
+
43
+ client = SettleClient(
44
+ base_url="https://api.agenticsettle.io",
45
+ api_key=os.environ["AGENTIC_SETTLE_API_KEY"],
46
+ )
47
+
48
+ receipt = client.settle(
49
+ agent_id="gpt-4o",
50
+ request_content="What is the capital of France?",
51
+ result_content="Paris",
52
+ target_wallet="0x0000000000000000000000000000000000000000",
53
+ )
54
+
55
+ print(receipt.status, receipt.chain_tx_hash)
56
+ ```
57
+
58
+ ## Quickstart (asyncio)
59
+
60
+ ```python
61
+ import asyncio
62
+ from agentic_settle import AsyncSettleClient
63
+
64
+ async def main() -> None:
65
+ client = AsyncSettleClient(api_key="...")
66
+ receipt = await client.settle(
67
+ agent_id="claude-3.5",
68
+ request_content="...",
69
+ result_content="...",
70
+ target_wallet="0x...",
71
+ )
72
+ print(receipt)
73
+
74
+ asyncio.run(main())
75
+ ```
76
+
77
+ ## Environment variables
78
+
79
+ The client falls back to the following env vars when constructor arguments
80
+ are omitted:
81
+
82
+ | Variable | Purpose |
83
+ |-----------------------------|------------------------------------------|
84
+ | `AGENTIC_SETTLE_BASE_URL` | Base URL of the settlement service |
85
+ | `AGENTIC_SETTLE_API_KEY` | API key (preferred) |
86
+ | `BRUCE_SECRET_KEY` | Legacy fallback for local dev convenience |
87
+
88
+ ## What's in the box
89
+
90
+ - `SettleClient` — synchronous client (httpx under the hood)
91
+ - `AsyncSettleClient` — asyncio variant for high-throughput agents
92
+ - `SettleRequest` — request payload model (pydantic v2)
93
+ - `SettleReceipt` — response receipt model (pydantic v2)
94
+
95
+ Type annotations ship with `py.typed`.
96
+
97
+ ## License
98
+
99
+ Apache-2.0
@@ -0,0 +1,9 @@
1
+ agentic_settle/__init__.py,sha256=V9-KYkGHjFwz3xADF_sQ0XPsaTSmS17_aGbUvBdHY00,1712
2
+ agentic_settle/client.py,sha256=KXDezFuaWq7YedV-FuICzu469oWBjCxbJU82d_LYmwQ,16790
3
+ agentic_settle/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ agentic_settle/types.py,sha256=c7dLq470NWNjdi6yVlctdkNlzf9fUc5PRq7-eRps-mE,3913
5
+ agentic_settle-0.2.0.dist-info/licenses/LICENSE,sha256=6lqVWSCDJ3bFp196gtL9GrtU4SLZ_NfEXEptbiU1Kns,732
6
+ agentic_settle-0.2.0.dist-info/METADATA,sha256=2EgKLJsR8tLEE0HYM2r77h-6IuugrI6P1YtK6MKPL8c,3182
7
+ agentic_settle-0.2.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
8
+ agentic_settle-0.2.0.dist-info/top_level.txt,sha256=_-c1GL_v2geRrD2XkaUR1DUpExBEv-iYt27KgsZBdfI,15
9
+ agentic_settle-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,17 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ Copyright 2026 AgenticSettle.IO
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ http://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
@@ -0,0 +1 @@
1
+ agentic_settle