auctra 0.2.3__tar.gz
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.
- auctra-0.2.3/PKG-INFO +86 -0
- auctra-0.2.3/README.md +76 -0
- auctra-0.2.3/auctra/__init__.py +4 -0
- auctra-0.2.3/auctra/client.py +273 -0
- auctra-0.2.3/auctra.egg-info/PKG-INFO +86 -0
- auctra-0.2.3/auctra.egg-info/SOURCES.txt +8 -0
- auctra-0.2.3/auctra.egg-info/dependency_links.txt +1 -0
- auctra-0.2.3/auctra.egg-info/top_level.txt +1 -0
- auctra-0.2.3/pyproject.toml +20 -0
- auctra-0.2.3/setup.cfg +4 -0
auctra-0.2.3/PKG-INFO
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: auctra
|
|
3
|
+
Version: 0.2.3
|
|
4
|
+
Summary: Authority Protocol Python client — issue authority, execute actions, verify evidence
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://auctra.tech/docs
|
|
7
|
+
Keywords: auctra,ai-agents,authority,delegation
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# auctra (Python SDK)
|
|
12
|
+
|
|
13
|
+
Stage 0/1 Python client — same Authority Protocol as `@auctra/sdk`.
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install auctra # when published; local: pip install -e packages/python-sdk
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick start (with intent anchor)
|
|
20
|
+
|
|
21
|
+
High-risk actions require **`create_intent`** first, then pass the returned **`intent`** (id + `anchor_token`) on execute:
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from auctra import Auctra
|
|
25
|
+
|
|
26
|
+
client = Auctra(api_key="auctra_...", base_url="https://app.auctra.tech")
|
|
27
|
+
|
|
28
|
+
agent_id = "your-agent-uuid"
|
|
29
|
+
expires_at = "2027-01-01T00:00:00Z"
|
|
30
|
+
|
|
31
|
+
client.authority.issue(
|
|
32
|
+
subject=agent_id,
|
|
33
|
+
capabilities=["send_payment"],
|
|
34
|
+
expires_at=expires_at,
|
|
35
|
+
max_amount=500,
|
|
36
|
+
currency="USD",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
created = client.create_intent(
|
|
40
|
+
title="Pay matched vendor invoices",
|
|
41
|
+
intent_type="payment",
|
|
42
|
+
risk_level="high",
|
|
43
|
+
max_risk_level="critical",
|
|
44
|
+
allowed_action_types=["send_payment"],
|
|
45
|
+
expires_at=expires_at,
|
|
46
|
+
)
|
|
47
|
+
intent = created["intent"]
|
|
48
|
+
|
|
49
|
+
preview = client.action.evaluate(
|
|
50
|
+
agent_id=agent_id,
|
|
51
|
+
action_type="send_payment",
|
|
52
|
+
payload={"amount": 50, "currency": "USD"},
|
|
53
|
+
intent=intent,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
decision = client.action.execute(
|
|
57
|
+
agent_id=agent_id,
|
|
58
|
+
action_type="send_payment",
|
|
59
|
+
payload={"amount": 50, "currency": "USD", "target": "vendor:acme"},
|
|
60
|
+
intent=intent,
|
|
61
|
+
action={
|
|
62
|
+
"target": "vendor:acme",
|
|
63
|
+
"description": "Net-30 invoice payment",
|
|
64
|
+
"risk_level": "medium",
|
|
65
|
+
},
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
print(decision["decision"])
|
|
69
|
+
client.evidence.verify(payload=decision["evidence_payload"], evidence=decision["evidence"])
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### New-client gotcha
|
|
73
|
+
|
|
74
|
+
Sending only `claimed_intent_id` (without `intent_anchor_token` or the `intent` object) returns **`require_approval`** with a reason about the missing anchor. Pass `intent=` from `create_intent`, or set both `claimed_intent_id` and `intent_anchor_token` explicitly.
|
|
75
|
+
|
|
76
|
+
See [`docs/integrations/intent-anchors.md`](../../docs/integrations/intent-anchors.md).
|
|
77
|
+
|
|
78
|
+
## Public surface
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
client.create_intent
|
|
82
|
+
client.authority.issue | verify | delegate | revoke
|
|
83
|
+
client.action.evaluate | execute
|
|
84
|
+
client.get_action_request
|
|
85
|
+
client.evidence.verify
|
|
86
|
+
```
|
auctra-0.2.3/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# auctra (Python SDK)
|
|
2
|
+
|
|
3
|
+
Stage 0/1 Python client — same Authority Protocol as `@auctra/sdk`.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pip install auctra # when published; local: pip install -e packages/python-sdk
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Quick start (with intent anchor)
|
|
10
|
+
|
|
11
|
+
High-risk actions require **`create_intent`** first, then pass the returned **`intent`** (id + `anchor_token`) on execute:
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from auctra import Auctra
|
|
15
|
+
|
|
16
|
+
client = Auctra(api_key="auctra_...", base_url="https://app.auctra.tech")
|
|
17
|
+
|
|
18
|
+
agent_id = "your-agent-uuid"
|
|
19
|
+
expires_at = "2027-01-01T00:00:00Z"
|
|
20
|
+
|
|
21
|
+
client.authority.issue(
|
|
22
|
+
subject=agent_id,
|
|
23
|
+
capabilities=["send_payment"],
|
|
24
|
+
expires_at=expires_at,
|
|
25
|
+
max_amount=500,
|
|
26
|
+
currency="USD",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
created = client.create_intent(
|
|
30
|
+
title="Pay matched vendor invoices",
|
|
31
|
+
intent_type="payment",
|
|
32
|
+
risk_level="high",
|
|
33
|
+
max_risk_level="critical",
|
|
34
|
+
allowed_action_types=["send_payment"],
|
|
35
|
+
expires_at=expires_at,
|
|
36
|
+
)
|
|
37
|
+
intent = created["intent"]
|
|
38
|
+
|
|
39
|
+
preview = client.action.evaluate(
|
|
40
|
+
agent_id=agent_id,
|
|
41
|
+
action_type="send_payment",
|
|
42
|
+
payload={"amount": 50, "currency": "USD"},
|
|
43
|
+
intent=intent,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
decision = client.action.execute(
|
|
47
|
+
agent_id=agent_id,
|
|
48
|
+
action_type="send_payment",
|
|
49
|
+
payload={"amount": 50, "currency": "USD", "target": "vendor:acme"},
|
|
50
|
+
intent=intent,
|
|
51
|
+
action={
|
|
52
|
+
"target": "vendor:acme",
|
|
53
|
+
"description": "Net-30 invoice payment",
|
|
54
|
+
"risk_level": "medium",
|
|
55
|
+
},
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
print(decision["decision"])
|
|
59
|
+
client.evidence.verify(payload=decision["evidence_payload"], evidence=decision["evidence"])
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### New-client gotcha
|
|
63
|
+
|
|
64
|
+
Sending only `claimed_intent_id` (without `intent_anchor_token` or the `intent` object) returns **`require_approval`** with a reason about the missing anchor. Pass `intent=` from `create_intent`, or set both `claimed_intent_id` and `intent_anchor_token` explicitly.
|
|
65
|
+
|
|
66
|
+
See [`docs/integrations/intent-anchors.md`](../../docs/integrations/intent-anchors.md).
|
|
67
|
+
|
|
68
|
+
## Public surface
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
client.create_intent
|
|
72
|
+
client.authority.issue | verify | delegate | revoke
|
|
73
|
+
client.action.evaluate | execute
|
|
74
|
+
client.get_action_request
|
|
75
|
+
client.evidence.verify
|
|
76
|
+
```
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import urllib.error
|
|
5
|
+
import urllib.request
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
__version__ = "0.2.3"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AuctraApiError(Exception):
|
|
12
|
+
def __init__(self, status: int, message: str, body: Any | None = None) -> None:
|
|
13
|
+
super().__init__(message)
|
|
14
|
+
self.status = status
|
|
15
|
+
self.body = body
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _normalize_guard_blocked(payload: Any, status: int) -> dict[str, Any]:
|
|
19
|
+
data = payload if isinstance(payload, dict) else {}
|
|
20
|
+
reason = data.get("reason") or data.get("error") or "Blocked before evaluation"
|
|
21
|
+
action_request_id = data.get("action_request_id")
|
|
22
|
+
guard_error = data.get("error")
|
|
23
|
+
return {
|
|
24
|
+
"decision": "blocked",
|
|
25
|
+
"reason": reason,
|
|
26
|
+
"action_request_id": action_request_id if isinstance(action_request_id, str) else None,
|
|
27
|
+
"guard": {
|
|
28
|
+
"httpStatus": status,
|
|
29
|
+
"error": guard_error if isinstance(guard_error, str) else None,
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class _AuthorityAPI:
|
|
35
|
+
def __init__(self, client: "Auctra") -> None:
|
|
36
|
+
self._client = client
|
|
37
|
+
|
|
38
|
+
def issue(
|
|
39
|
+
self,
|
|
40
|
+
*,
|
|
41
|
+
subject: str,
|
|
42
|
+
capabilities: list[str],
|
|
43
|
+
expires_at: str,
|
|
44
|
+
max_amount: float | None = None,
|
|
45
|
+
currency: str | None = None,
|
|
46
|
+
parent: str | None = None,
|
|
47
|
+
) -> dict[str, Any]:
|
|
48
|
+
body: dict[str, Any] = {
|
|
49
|
+
"agent_id": subject,
|
|
50
|
+
"action_types": capabilities,
|
|
51
|
+
"valid_until": expires_at,
|
|
52
|
+
}
|
|
53
|
+
if max_amount is not None:
|
|
54
|
+
body["max_amount"] = max_amount
|
|
55
|
+
if currency is not None:
|
|
56
|
+
body["currency"] = currency
|
|
57
|
+
if parent is not None:
|
|
58
|
+
body["parent_authority_id"] = parent
|
|
59
|
+
return self._client._request("POST", "/v1/authorities", body)
|
|
60
|
+
|
|
61
|
+
def delegate(
|
|
62
|
+
self,
|
|
63
|
+
*,
|
|
64
|
+
parent: str,
|
|
65
|
+
subject: str,
|
|
66
|
+
capabilities: list[str],
|
|
67
|
+
expires_at: str,
|
|
68
|
+
max_amount: float | None = None,
|
|
69
|
+
currency: str | None = None,
|
|
70
|
+
) -> dict[str, Any]:
|
|
71
|
+
return self.issue(
|
|
72
|
+
subject=subject,
|
|
73
|
+
capabilities=capabilities,
|
|
74
|
+
expires_at=expires_at,
|
|
75
|
+
max_amount=max_amount,
|
|
76
|
+
currency=currency,
|
|
77
|
+
parent=parent,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
def revoke(self, authority_id: str) -> dict[str, Any]:
|
|
81
|
+
return self._client._request("POST", f"/v1/authorities/{authority_id}/revoke", {})
|
|
82
|
+
|
|
83
|
+
def verify(self, *, payload: dict[str, Any], artifact: dict[str, Any]) -> dict[str, Any]:
|
|
84
|
+
return self._client._request(
|
|
85
|
+
"POST",
|
|
86
|
+
"/v1/authorities/verify",
|
|
87
|
+
{"payload": payload, "artifact": artifact},
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class _ActionAPI:
|
|
92
|
+
def __init__(self, client: "Auctra") -> None:
|
|
93
|
+
self._client = client
|
|
94
|
+
|
|
95
|
+
def evaluate(
|
|
96
|
+
self,
|
|
97
|
+
*,
|
|
98
|
+
agent_id: str,
|
|
99
|
+
action_type: str,
|
|
100
|
+
payload: dict[str, Any] | None = None,
|
|
101
|
+
claimed_intent_id: str | None = None,
|
|
102
|
+
intent_anchor_token: str | None = None,
|
|
103
|
+
intent: dict[str, Any] | None = None,
|
|
104
|
+
) -> dict[str, Any]:
|
|
105
|
+
body: dict[str, Any] = {
|
|
106
|
+
"agent_id": agent_id,
|
|
107
|
+
"action_type": action_type,
|
|
108
|
+
"payload": payload or {},
|
|
109
|
+
"dry_run": True,
|
|
110
|
+
}
|
|
111
|
+
intent_id = claimed_intent_id or (intent or {}).get("id")
|
|
112
|
+
anchor = intent_anchor_token or (intent or {}).get("anchor_token") or (intent or {}).get(
|
|
113
|
+
"anchorToken"
|
|
114
|
+
)
|
|
115
|
+
if intent_id:
|
|
116
|
+
body["claimed_intent_id"] = intent_id
|
|
117
|
+
if anchor:
|
|
118
|
+
body["intent_anchor_token"] = anchor
|
|
119
|
+
return self._client._request(
|
|
120
|
+
"POST",
|
|
121
|
+
"/v1/actions/evaluate",
|
|
122
|
+
body,
|
|
123
|
+
normalize_guard_blocked=True,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
def execute(
|
|
127
|
+
self,
|
|
128
|
+
*,
|
|
129
|
+
agent_id: str,
|
|
130
|
+
action_type: str,
|
|
131
|
+
payload: dict[str, Any] | None = None,
|
|
132
|
+
claimed_intent_id: str | None = None,
|
|
133
|
+
intent_anchor_token: str | None = None,
|
|
134
|
+
intent: dict[str, Any] | None = None,
|
|
135
|
+
) -> dict[str, Any]:
|
|
136
|
+
body: dict[str, Any] = {
|
|
137
|
+
"agent_id": agent_id,
|
|
138
|
+
"action_type": action_type,
|
|
139
|
+
"payload": payload or {},
|
|
140
|
+
"dry_run": False,
|
|
141
|
+
}
|
|
142
|
+
intent_id = claimed_intent_id or (intent or {}).get("id")
|
|
143
|
+
anchor = intent_anchor_token or (intent or {}).get("anchor_token") or (intent or {}).get(
|
|
144
|
+
"anchorToken"
|
|
145
|
+
)
|
|
146
|
+
if intent_id:
|
|
147
|
+
body["claimed_intent_id"] = intent_id
|
|
148
|
+
if anchor:
|
|
149
|
+
body["intent_anchor_token"] = anchor
|
|
150
|
+
return self._client._request(
|
|
151
|
+
"POST",
|
|
152
|
+
"/v1/actions/execute",
|
|
153
|
+
body,
|
|
154
|
+
normalize_guard_blocked=True,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class _EvidenceAPI:
|
|
159
|
+
def __init__(self, client: "Auctra") -> None:
|
|
160
|
+
self._client = client
|
|
161
|
+
|
|
162
|
+
def verify(self, *, payload: dict[str, Any], evidence: dict[str, Any]) -> dict[str, Any]:
|
|
163
|
+
return self._client._request(
|
|
164
|
+
"POST",
|
|
165
|
+
"/v1/evidence/verify",
|
|
166
|
+
{"payload": payload, "evidence": evidence},
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
DEFAULT_BASE_URL = "https://app.auctra.tech"
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class Auctra:
|
|
174
|
+
def __init__(
|
|
175
|
+
self,
|
|
176
|
+
api_key: str,
|
|
177
|
+
base_url: str = DEFAULT_BASE_URL,
|
|
178
|
+
timeout: float = 30.0,
|
|
179
|
+
) -> None:
|
|
180
|
+
self.api_key = api_key
|
|
181
|
+
self.base_url = base_url.rstrip("/")
|
|
182
|
+
self.timeout = timeout
|
|
183
|
+
self.authority = _AuthorityAPI(self)
|
|
184
|
+
self.action = _ActionAPI(self)
|
|
185
|
+
self.evidence = _EvidenceAPI(self)
|
|
186
|
+
|
|
187
|
+
def _request(
|
|
188
|
+
self,
|
|
189
|
+
method: str,
|
|
190
|
+
path: str,
|
|
191
|
+
body: dict[str, Any] | None = None,
|
|
192
|
+
*,
|
|
193
|
+
normalize_guard_blocked: bool = False,
|
|
194
|
+
) -> Any:
|
|
195
|
+
url = f"{self.base_url}{path}"
|
|
196
|
+
data = None if body is None else json.dumps(body).encode("utf-8")
|
|
197
|
+
request = urllib.request.Request(
|
|
198
|
+
url,
|
|
199
|
+
data=data,
|
|
200
|
+
method=method,
|
|
201
|
+
headers={
|
|
202
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
203
|
+
"Content-Type": "application/json",
|
|
204
|
+
"Accept": "application/json",
|
|
205
|
+
# Cloudflare bot score can block bare urllib user-agents (Error 1010).
|
|
206
|
+
"User-Agent": f"auctra-python-sdk/{__version__} (+https://auctra.tech)",
|
|
207
|
+
},
|
|
208
|
+
)
|
|
209
|
+
try:
|
|
210
|
+
with urllib.request.urlopen(request, timeout=self.timeout) as response:
|
|
211
|
+
return json.loads(response.read().decode("utf-8"))
|
|
212
|
+
except urllib.error.HTTPError as error:
|
|
213
|
+
payload = None
|
|
214
|
+
try:
|
|
215
|
+
payload = json.loads(error.read().decode("utf-8"))
|
|
216
|
+
except Exception:
|
|
217
|
+
payload = None
|
|
218
|
+
if (
|
|
219
|
+
normalize_guard_blocked
|
|
220
|
+
and error.code in (400, 404)
|
|
221
|
+
and isinstance(payload, dict)
|
|
222
|
+
and payload.get("decision") == "blocked"
|
|
223
|
+
):
|
|
224
|
+
return _normalize_guard_blocked(payload, error.code)
|
|
225
|
+
message = payload.get("error") if isinstance(payload, dict) else str(error)
|
|
226
|
+
raise AuctraApiError(error.code, message or "Request failed", payload) from error
|
|
227
|
+
|
|
228
|
+
def verify_audit_chain(self) -> dict[str, Any]:
|
|
229
|
+
return self._request("GET", "/v1/audit-events/verify")
|
|
230
|
+
|
|
231
|
+
def get_audit_event(self, audit_event_id: str) -> dict[str, Any]:
|
|
232
|
+
return self._request("GET", f"/v1/audit-events/{audit_event_id}")
|
|
233
|
+
|
|
234
|
+
def verify_mandate(self, *, payload: dict[str, Any], evidence: dict[str, Any]) -> dict[str, Any]:
|
|
235
|
+
return self._request(
|
|
236
|
+
"POST",
|
|
237
|
+
"/v1/mandates/verify",
|
|
238
|
+
{"payload": payload, "evidence": evidence},
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
def list_audit_events(self) -> dict[str, Any]:
|
|
242
|
+
return self._request("GET", "/v1/audit-events")
|
|
243
|
+
|
|
244
|
+
def get_action_request(self, action_request_id: str) -> dict[str, Any]:
|
|
245
|
+
"""Dispute pack: decision, receipt, evidence, audit anchors."""
|
|
246
|
+
return self._request("GET", f"/v1/action-requests/{action_request_id}")
|
|
247
|
+
|
|
248
|
+
def create_intent(
|
|
249
|
+
self,
|
|
250
|
+
*,
|
|
251
|
+
title: str,
|
|
252
|
+
description: str | None = None,
|
|
253
|
+
intent_type: str | None = None,
|
|
254
|
+
risk_level: str = "medium",
|
|
255
|
+
max_risk_level: str = "high",
|
|
256
|
+
allowed_action_types: list[str] | None = None,
|
|
257
|
+
expires_at: str | None = None,
|
|
258
|
+
) -> dict[str, Any]:
|
|
259
|
+
"""Declare a human intent. Response includes anchor_token for action.execute."""
|
|
260
|
+
body: dict[str, Any] = {
|
|
261
|
+
"title": title,
|
|
262
|
+
"risk_level": risk_level,
|
|
263
|
+
"max_risk_level": max_risk_level,
|
|
264
|
+
}
|
|
265
|
+
if description is not None:
|
|
266
|
+
body["description"] = description
|
|
267
|
+
if intent_type is not None:
|
|
268
|
+
body["intent_type"] = intent_type
|
|
269
|
+
if allowed_action_types is not None:
|
|
270
|
+
body["allowed_action_types"] = allowed_action_types
|
|
271
|
+
if expires_at is not None:
|
|
272
|
+
body["expires_at"] = expires_at
|
|
273
|
+
return self._request("POST", "/v1/intents", body)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: auctra
|
|
3
|
+
Version: 0.2.3
|
|
4
|
+
Summary: Authority Protocol Python client — issue authority, execute actions, verify evidence
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://auctra.tech/docs
|
|
7
|
+
Keywords: auctra,ai-agents,authority,delegation
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# auctra (Python SDK)
|
|
12
|
+
|
|
13
|
+
Stage 0/1 Python client — same Authority Protocol as `@auctra/sdk`.
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install auctra # when published; local: pip install -e packages/python-sdk
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick start (with intent anchor)
|
|
20
|
+
|
|
21
|
+
High-risk actions require **`create_intent`** first, then pass the returned **`intent`** (id + `anchor_token`) on execute:
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from auctra import Auctra
|
|
25
|
+
|
|
26
|
+
client = Auctra(api_key="auctra_...", base_url="https://app.auctra.tech")
|
|
27
|
+
|
|
28
|
+
agent_id = "your-agent-uuid"
|
|
29
|
+
expires_at = "2027-01-01T00:00:00Z"
|
|
30
|
+
|
|
31
|
+
client.authority.issue(
|
|
32
|
+
subject=agent_id,
|
|
33
|
+
capabilities=["send_payment"],
|
|
34
|
+
expires_at=expires_at,
|
|
35
|
+
max_amount=500,
|
|
36
|
+
currency="USD",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
created = client.create_intent(
|
|
40
|
+
title="Pay matched vendor invoices",
|
|
41
|
+
intent_type="payment",
|
|
42
|
+
risk_level="high",
|
|
43
|
+
max_risk_level="critical",
|
|
44
|
+
allowed_action_types=["send_payment"],
|
|
45
|
+
expires_at=expires_at,
|
|
46
|
+
)
|
|
47
|
+
intent = created["intent"]
|
|
48
|
+
|
|
49
|
+
preview = client.action.evaluate(
|
|
50
|
+
agent_id=agent_id,
|
|
51
|
+
action_type="send_payment",
|
|
52
|
+
payload={"amount": 50, "currency": "USD"},
|
|
53
|
+
intent=intent,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
decision = client.action.execute(
|
|
57
|
+
agent_id=agent_id,
|
|
58
|
+
action_type="send_payment",
|
|
59
|
+
payload={"amount": 50, "currency": "USD", "target": "vendor:acme"},
|
|
60
|
+
intent=intent,
|
|
61
|
+
action={
|
|
62
|
+
"target": "vendor:acme",
|
|
63
|
+
"description": "Net-30 invoice payment",
|
|
64
|
+
"risk_level": "medium",
|
|
65
|
+
},
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
print(decision["decision"])
|
|
69
|
+
client.evidence.verify(payload=decision["evidence_payload"], evidence=decision["evidence"])
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### New-client gotcha
|
|
73
|
+
|
|
74
|
+
Sending only `claimed_intent_id` (without `intent_anchor_token` or the `intent` object) returns **`require_approval`** with a reason about the missing anchor. Pass `intent=` from `create_intent`, or set both `claimed_intent_id` and `intent_anchor_token` explicitly.
|
|
75
|
+
|
|
76
|
+
See [`docs/integrations/intent-anchors.md`](../../docs/integrations/intent-anchors.md).
|
|
77
|
+
|
|
78
|
+
## Public surface
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
client.create_intent
|
|
82
|
+
client.authority.issue | verify | delegate | revoke
|
|
83
|
+
client.action.evaluate | execute
|
|
84
|
+
client.get_action_request
|
|
85
|
+
client.evidence.verify
|
|
86
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
auctra
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "auctra"
|
|
7
|
+
version = "0.2.3"
|
|
8
|
+
description = "Authority Protocol Python client — issue authority, execute actions, verify evidence"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
keywords = ["auctra", "ai-agents", "authority", "delegation"]
|
|
13
|
+
dependencies = []
|
|
14
|
+
|
|
15
|
+
[project.urls]
|
|
16
|
+
Homepage = "https://auctra.tech/docs"
|
|
17
|
+
|
|
18
|
+
[tool.setuptools.packages.find]
|
|
19
|
+
where = ["."]
|
|
20
|
+
include = ["auctra*"]
|
auctra-0.2.3/setup.cfg
ADDED