Skip to content

Commit a52dde2

Browse files
authored
docs: README overhaul and diagram integration (#21)
* docs: overhaul README structure and narrative Rewrite root README with integrated diagrams, repository context, cross-repo references, and explicit alpha feedback contact details. * docs: add README-linked diagram assets Add SVG assets referenced by the root README so diagrams render correctly in GitHub for this repository.
1 parent 5a1cd0f commit a52dde2

File tree

4 files changed

+874
-176
lines changed

4 files changed

+874
-176
lines changed

README.md

Lines changed: 182 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -1,197 +1,203 @@
11
# axme-sdk-python
22

3-
Official Python SDK for Axme APIs and workflows.
3+
**Official Python SDK for the AXME platform.** Send and manage intents, observe lifecycle events, work with inbox and approvals, and access the full enterprise admin surface — all from idiomatic Python.
44

5-
Canonical protocol positioning:
5+
> **Alpha** · API surface is stabilizing. Not recommended for production workloads yet.
6+
> Bug reports, feedback, and alpha access → [hello@axme.ai](mailto:hello@axme.ai)
67
7-
- **AXP is the Intent Protocol (durable execution layer).**
8+
---
89

9-
## Status
10+
## What You Can Do With This SDK
1011

11-
Initial v1 skeleton in progress.
12+
The AXME Python SDK gives you a fully typed client for the AXME platform. You can:
13+
14+
- **Send intents** — create typed, durable actions that the platform guarantees to deliver
15+
- **Observe lifecycle** — stream real-time state transitions, waiting events, and delivery confirmations
16+
- **Approve or reject** — handle human-in-the-loop steps directly from Python code
17+
- **Control workflows** — pause, resume, cancel, update retry policies and reminders mid-flight
18+
- **Administer** — manage organizations, workspaces, service accounts, and access grants
19+
20+
---
21+
22+
## Install
23+
24+
```bash
25+
pip install axme-sdk
26+
```
27+
28+
For local development from source:
29+
30+
```bash
31+
python -m pip install -e ".[dev]"
32+
```
33+
34+
---
1235

1336
## Quickstart
1437

1538
```python
1639
from axme_sdk import AxmeClient, AxmeClientConfig
1740

18-
config = AxmeClientConfig(
19-
base_url="https://gateway.example.com",
20-
api_key="YOUR_API_KEY",
21-
max_retries=2,
22-
retry_backoff_seconds=0.2,
41+
client = AxmeClient(
42+
AxmeClientConfig(
43+
base_url="https://gateway.axme.ai",
44+
api_key="YOUR_API_KEY",
45+
)
2346
)
2447

25-
with AxmeClient(config) as client:
26-
print(client.health(trace_id="trace-quickstart-001"))
27-
result = client.create_intent(
28-
{
29-
"intent_type": "notify.message.v1",
30-
"from_agent": "agent://example/sender",
31-
"to_agent": "agent://example/receiver",
32-
"payload": {"text": "hello"},
33-
},
34-
correlation_id="11111111-1111-1111-1111-111111111111",
35-
idempotency_key="create-intent-001",
36-
)
37-
print(result)
38-
print(client.get_intent(result["intent_id"])["intent"]["status"])
39-
sent_intent_id = client.send_intent(
40-
{
41-
"intent_type": "notify.message.v1",
42-
"from_agent": "agent://example/sender",
43-
"to_agent": "agent://example/receiver",
44-
"payload": {"text": "hello again"},
45-
},
46-
idempotency_key="send-intent-001",
47-
)
48-
print(sent_intent_id)
49-
print(client.list_intent_events(sent_intent_id, since=0))
50-
for event in client.observe(sent_intent_id, since=0, wait_seconds=10):
51-
print(event["event_type"], event["status"])
52-
if event["status"] in {"COMPLETED", "FAILED", "CANCELED"}:
53-
break
54-
terminal = client.wait_for(sent_intent_id, timeout_seconds=30)
55-
print(terminal["status"])
56-
inbox = client.list_inbox(owner_agent="agent://example/receiver", trace_id="trace-inbox-001")
57-
print(inbox)
58-
thread = client.get_inbox_thread("11111111-1111-4111-8111-111111111111", owner_agent="agent://example/receiver")
59-
print(thread["thread"]["status"])
60-
changes = client.list_inbox_changes(owner_agent="agent://example/receiver", limit=50)
61-
print(changes["next_cursor"], changes["has_more"])
62-
replied = client.reply_inbox_thread(
63-
"11111111-1111-4111-8111-111111111111",
64-
message="Acknowledged",
65-
owner_agent="agent://example/receiver",
66-
idempotency_key="reply-001",
67-
)
68-
print(replied)
69-
delegated = client.delegate_inbox_thread(
70-
"11111111-1111-4111-8111-111111111111",
71-
{"delegate_to": "agent://example/delegate", "note": "handoff"},
72-
owner_agent="agent://example/receiver",
73-
idempotency_key="delegate-001",
74-
)
75-
print(delegated["thread"]["status"])
76-
approved = client.approve_inbox_thread(
77-
"11111111-1111-4111-8111-111111111111",
78-
{"comment": "approved"},
79-
owner_agent="agent://example/receiver",
80-
idempotency_key="approve-001",
81-
)
82-
print(approved["thread"]["status"])
83-
rejected = client.reject_inbox_thread(
84-
"11111111-1111-4111-8111-111111111111",
85-
{"comment": "rejected"},
86-
owner_agent="agent://example/receiver",
87-
idempotency_key="reject-001",
88-
)
89-
print(rejected["thread"]["status"])
90-
deleted = client.delete_inbox_messages(
91-
"11111111-1111-4111-8111-111111111111",
92-
{"mode": "self", "limit": 1},
93-
owner_agent="agent://example/receiver",
94-
idempotency_key="delete-001",
95-
)
96-
print(deleted["deleted_count"])
97-
approval = client.decide_approval(
98-
"55555555-5555-4555-8555-555555555555",
99-
decision="approve",
100-
comment="Looks good",
101-
idempotency_key="approval-001",
102-
)
103-
print(approval["approval"]["decision"])
104-
capabilities = client.get_capabilities()
105-
print(capabilities["supported_intent_types"])
106-
invite = client.create_invite(
107-
{"owner_agent": "agent://example/receiver", "recipient_hint": "Partner A", "ttl_seconds": 3600},
108-
idempotency_key="invite-create-001",
109-
)
110-
print(invite["token"])
111-
invite_details = client.get_invite(invite["token"])
112-
print(invite_details["status"])
113-
accepted = client.accept_invite(
114-
invite["token"],
115-
{"nick": "@PartnerA.User", "display_name": "Partner A"},
116-
idempotency_key="invite-accept-001",
117-
)
118-
print(accepted["public_address"])
119-
media_upload = client.create_media_upload(
120-
{
121-
"owner_agent": "agent://example/receiver",
122-
"filename": "contract.pdf",
123-
"mime_type": "application/pdf",
124-
"size_bytes": 12345,
125-
},
126-
idempotency_key="media-create-001",
127-
)
128-
print(media_upload["upload_id"])
129-
media_state = client.get_media_upload(media_upload["upload_id"])
130-
print(media_state["upload"]["status"])
131-
finalized = client.finalize_media_upload(
132-
{"upload_id": media_upload["upload_id"], "size_bytes": 12345},
133-
idempotency_key="media-finalize-001",
134-
)
135-
print(finalized["status"])
136-
schema = client.upsert_schema(
137-
{
138-
"semantic_type": "axme.calendar.schedule.v1",
139-
"schema_json": {"type": "object", "required": ["date"], "properties": {"date": {"type": "string"}}},
140-
"compatibility_mode": "strict",
141-
},
142-
idempotency_key="schema-upsert-001",
143-
)
144-
print(schema["schema"]["schema_hash"])
145-
schema_get = client.get_schema("axme.calendar.schedule.v1")
146-
print(schema_get["schema"]["semantic_type"])
147-
registered = client.register_nick(
148-
{"nick": "@partner.user", "display_name": "Partner User"},
149-
idempotency_key="nick-register-001",
150-
)
151-
print(registered["owner_agent"])
152-
nick_check = client.check_nick("@partner.user")
153-
print(nick_check["available"])
154-
renamed = client.rename_nick(
155-
{"owner_agent": registered["owner_agent"], "nick": "@partner.new"},
156-
idempotency_key="nick-rename-001",
157-
)
158-
print(renamed["public_address"])
159-
profile = client.get_user_profile(registered["owner_agent"])
160-
print(profile["updated_at"])
161-
profile_updated = client.update_user_profile(
162-
{"owner_agent": registered["owner_agent"], "display_name": "Partner User Updated"},
163-
idempotency_key="profile-update-001",
164-
)
165-
print(profile_updated["display_name"])
166-
subscription = client.upsert_webhook_subscription(
167-
{
168-
"callback_url": "https://integrator.example/webhooks/axme",
169-
"event_types": ["inbox.thread_created"],
170-
"active": True,
48+
# Check connectivity
49+
print(client.health())
50+
51+
# Send an intent
52+
intent = client.create_intent(
53+
{
54+
"intent_type": "order.fulfillment.v1",
55+
"payload": {"order_id": "ord_123", "priority": "high"},
56+
"owner_agent": "agent://fulfillment-service",
57+
},
58+
idempotency_key="fulfill-ord-123-001",
59+
)
60+
print(intent["intent_id"], intent["status"])
61+
62+
# Wait for resolution
63+
resolved = client.wait_for(intent["intent_id"], terminal_states={"RESOLVED", "CANCELLED"})
64+
print(resolved["status"])
65+
```
66+
67+
---
68+
69+
## API Method Families
70+
71+
The SDK covers the full public API surface organized into families. The map below shows all method groups and how they relate to the platform's intent lifecycle.
72+
73+
![API Method Family Map](docs/diagrams/01-api-method-family-map.svg)
74+
75+
*Each family corresponds to a segment of the lifecycle or an operational domain. Intents and inbox are D1 (core). Approvals, schemas, and media are D2. Enterprise admin and service accounts are D3.*
76+
77+
---
78+
79+
## Create and Control Sequence
80+
81+
From calling `create_intent()` to receiving a delivery confirmation — the full interaction sequence with the platform:
82+
83+
![Create and Control Sequence](docs/diagrams/02-create-and-control-sequence.svg)
84+
85+
*The SDK sets the `Idempotency-Key` and `X-Correlation-Id` headers automatically. The gateway validates, persists, and returns the intent in `PENDING` state. The scheduler picks it up and drives delivery.*
86+
87+
---
88+
89+
## Idempotency and Replay Protection
90+
91+
Every mutating call in the SDK accepts an optional `idempotency_key`. Use it for all operations you might retry.
92+
93+
![Idempotency and Replay Protection](docs/diagrams/03-idempotency-and-replay-protection.svg)
94+
95+
*Duplicate requests with the same key return the original response without re-executing. Keys expire after 24 hours. The SDK will warn if you reuse a key with different parameters.*
96+
97+
```python
98+
# Safe to call multiple times — only executes once
99+
intent = client.create_intent(payload, idempotency_key="my-unique-key-001")
100+
```
101+
102+
---
103+
104+
## Observing Intent Events
105+
106+
The SDK provides a streaming event observer that delivers real-time lifecycle events over SSE:
107+
108+
```python
109+
for event in client.observe(intent["intent_id"]):
110+
print(event["event_type"], event["status"])
111+
if event["status"] in {"RESOLVED", "CANCELLED", "EXPIRED"}:
112+
break
113+
```
114+
115+
---
116+
117+
## Approvals and Human-in-the-Loop
118+
119+
```python
120+
# Fetch pending approvals for an agent
121+
pending = client.list_inbox({"owner_agent": "agent://manager", "status": "PENDING"})
122+
123+
for item in pending["items"]:
124+
# Approve with a note
125+
client.resolve_approval(item["intent_id"], {"decision": "approved", "note": "LGTM"})
126+
```
127+
128+
---
129+
130+
## Workflow Controls
131+
132+
Update retry policy, reminders, or TTL on a live intent without cancelling it:
133+
134+
```python
135+
client.update_intent_controls(
136+
intent_id,
137+
{
138+
"controls": {
139+
"max_retries": 5,
140+
"retry_delay_seconds": 30,
141+
"reminders": [{"offset_seconds": 3600, "note": "1h reminder"}],
171142
}
172-
)
173-
print(subscription)
174-
events = client.publish_webhook_event(
175-
{"event_type": "inbox.thread_created", "source": "sdk-example", "payload": {"thread_id": "t-1"}},
176-
owner_agent="agent://example/receiver",
177-
)
178-
print(events["event_id"])
179-
mcp_info = client.mcp_initialize()
180-
print(mcp_info["protocolVersion"])
181-
tools = client.mcp_list_tools()
182-
print(len(tools.get("tools", [])))
183-
mcp_result = client.mcp_call_tool(
184-
"axme.send",
185-
arguments={"to": "agent://example/receiver", "text": "hello from MCP"},
186-
owner_agent="agent://example/receiver",
187-
idempotency_key="mcp-send-001",
188-
)
189-
print(mcp_result.get("status"))
143+
},
144+
policy_generation=intent["policy_generation"],
145+
)
190146
```
191147

192-
## Development
148+
---
149+
150+
## SDK Diagrams
151+
152+
The SDK docs folder contains diagrams for the API patterns used by this client:
153+
154+
| Diagram | Description |
155+
|---|---|
156+
| [`01-api-method-family-map`](docs/diagrams/01-api-method-family-map.svg) | Full API family overview |
157+
| [`02-create-and-control-sequence`](docs/diagrams/02-create-and-control-sequence.svg) | Intent creation and control flow |
158+
| [`03-idempotency-and-replay-protection`](docs/diagrams/03-idempotency-and-replay-protection.svg) | Idempotency protocol |
159+
160+
---
161+
162+
## Tests
193163

194164
```bash
195-
python -m pip install -e ".[dev]"
196165
pytest
197166
```
167+
168+
---
169+
170+
## Repository Structure
171+
172+
```
173+
axme-sdk-python/
174+
├── axme_sdk/
175+
│ ├── client.py # AxmeClient — all API methods
176+
│ ├── config.py # AxmeClientConfig
177+
│ └── exceptions.py # AxmeAPIError and subclasses
178+
├── tests/ # Unit and integration tests
179+
└── docs/
180+
└── diagrams/ # Diagram copies for README embedding
181+
```
182+
183+
---
184+
185+
## Related Repositories
186+
187+
| Repository | Role |
188+
|---|---|
189+
| [axme-docs](https://github.com/AxmeAI/axme-docs) | Full API reference and integration guides |
190+
| [axme-spec](https://github.com/AxmeAI/axme-spec) | Schema contracts this SDK implements |
191+
| [axme-conformance](https://github.com/AxmeAI/axme-conformance) | Conformance suite that validates this SDK |
192+
| [axme-examples](https://github.com/AxmeAI/axme-examples) | Runnable examples using this SDK |
193+
| [axme-sdk-typescript](https://github.com/AxmeAI/axme-sdk-typescript) | TypeScript equivalent |
194+
| [axme-sdk-go](https://github.com/AxmeAI/axme-sdk-go) | Go equivalent |
195+
196+
---
197+
198+
## Contributing & Contact
199+
200+
- Bug reports and feature requests: open an issue in this repository
201+
- Alpha program access and integration questions: [hello@axme.ai](mailto:hello@axme.ai)
202+
- Security disclosures: see [SECURITY.md](SECURITY.md)
203+
- Contribution guidelines: [CONTRIBUTING.md](CONTRIBUTING.md)

0 commit comments

Comments
 (0)