agentverse-sdk 0.1.0__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.
Files changed (30) hide show
  1. agentverse_sdk-0.1.0/.gitignore +41 -0
  2. agentverse_sdk-0.1.0/DEVELOPER.md +430 -0
  3. agentverse_sdk-0.1.0/PKG-INFO +50 -0
  4. agentverse_sdk-0.1.0/README.md +23 -0
  5. agentverse_sdk-0.1.0/agentverse_sdk/__init__.py +3 -0
  6. agentverse_sdk-0.1.0/agentverse_sdk/_common/__init__.py +0 -0
  7. agentverse_sdk-0.1.0/agentverse_sdk/_common/av.py +160 -0
  8. agentverse_sdk-0.1.0/agentverse_sdk/_common/config.py +4 -0
  9. agentverse_sdk-0.1.0/agentverse_sdk/_common/events.py +210 -0
  10. agentverse_sdk-0.1.0/agentverse_sdk/_common/helpers.py +5 -0
  11. agentverse_sdk-0.1.0/agentverse_sdk/_common/logger.py +76 -0
  12. agentverse_sdk-0.1.0/agentverse_sdk/_common/starlette.py +120 -0
  13. agentverse_sdk-0.1.0/agentverse_sdk/_common/storage.py +70 -0
  14. agentverse_sdk-0.1.0/agentverse_sdk/_common/types.py +234 -0
  15. agentverse_sdk-0.1.0/agentverse_sdk/a2a/__init__.py +3 -0
  16. agentverse_sdk-0.1.0/agentverse_sdk/a2a/_app.py +266 -0
  17. agentverse_sdk-0.1.0/agentverse_sdk/a2a/content.py +212 -0
  18. agentverse_sdk-0.1.0/agentverse_sdk/a2a/profile.py +90 -0
  19. agentverse_sdk-0.1.0/agentverse_sdk/langgraph/__init__.py +3 -0
  20. agentverse_sdk-0.1.0/agentverse_sdk/langgraph/__main__.py +142 -0
  21. agentverse_sdk-0.1.0/agentverse_sdk/langgraph/_app.py +415 -0
  22. agentverse_sdk-0.1.0/agentverse_sdk/langgraph/config.py +21 -0
  23. agentverse_sdk-0.1.0/agentverse_sdk/langgraph/content.py +244 -0
  24. agentverse_sdk-0.1.0/agentverse_sdk/langgraph/profile.py +70 -0
  25. agentverse_sdk-0.1.0/pyproject.toml +70 -0
  26. agentverse_sdk-0.1.0/tests/conftest.py +29 -0
  27. agentverse_sdk-0.1.0/tests/test_langchain_content.py +769 -0
  28. agentverse_sdk-0.1.0/tests/test_registration.py +68 -0
  29. agentverse_sdk-0.1.0/tests/test_storage.py +125 -0
  30. agentverse_sdk-0.1.0/uagents_core.log +0 -0
@@ -0,0 +1,41 @@
1
+ # IDEs
2
+ .idea/
3
+ .DS_Store
4
+
5
+ # Data
6
+ *.sqlite*
7
+
8
+ # Python Specific
9
+ __pycache__
10
+ *.py[cgo]
11
+ *.egg-info/
12
+ .venv/
13
+ .pnpm-store/
14
+
15
+ # docker secrets
16
+ .env
17
+ # but allow test env files
18
+ !.env.test
19
+
20
+ # Cursor personal (machine-specific, not shared)
21
+ .cursor/rules/personal/
22
+ .cursor/commands/personal/
23
+
24
+ # vscode
25
+ .vscode/
26
+ .history/
27
+ # misc
28
+ .__untracked__
29
+
30
+ # vagrant
31
+ .vagrant/
32
+
33
+ # AVCTL Build directory
34
+ build/
35
+
36
+ # Goreleaser build directory
37
+ dist/
38
+
39
+ # ignore old mailbox-app folder
40
+ /ui/mailbox-app/# Lint fix verification
41
+ *.code-workspace
@@ -0,0 +1,430 @@
1
+ # Agentverse SDK — Developer Guide
2
+
3
+ ## Package Info
4
+
5
+ | | |
6
+ |---|---|
7
+ | **PyPI name** | `agentverse-sdk` |
8
+ | **Location** | `agentverse-core/pkg/agentverse-sdk/` (migrated from `uAgents/uagents-core/uagents_core/agentverse/sdk/`) |
9
+ | **Source package** | `agentverse_sdk` |
10
+ | **Core dependency** | `uagents-core` (external PyPI package — provides identity, envelope, chat protocol types) |
11
+
12
+ ### Public API
13
+
14
+ ```python
15
+ from agentverse_sdk.a2a import init # A2A adapter
16
+ from agentverse_sdk.langgraph import init # LangGraph adapter
17
+ ```
18
+
19
+ ### Install
20
+
21
+ ```bash
22
+ pip install agentverse-sdk[a2a] # A2A adapter
23
+ pip install agentverse-sdk[langgraph] # LangGraph adapter
24
+ ```
25
+
26
+ For local development (from monorepo root):
27
+
28
+ ```bash
29
+ pip install -e "pkg/agentverse-sdk[a2a,langgraph,dev]"
30
+ ```
31
+
32
+ ---
33
+
34
+ ## Objective
35
+
36
+ Connect any AI agent framework to [Agentverse](https://agentverse.ai) with zero user-facing configuration beyond a single URI string. The SDK:
37
+
38
+ 1. **Registers** the agent with Agentverse on startup.
39
+ 2. **Receives** chat messages via a Starlette POST endpoint (`/av/chat`).
40
+ 3. **Delegates** work to the underlying framework (LangGraph, A2A, etc.).
41
+ 4. **Replies** with the framework's output, converted to the chat protocol.
42
+ 5. **Reports** lifecycle events (start/stop) and errors to the Agentverse Events API.
43
+
44
+ The user's experience is: call `init("agentverse://...")` and the SDK handles everything else invisibly.
45
+
46
+ ---
47
+
48
+ ## Philosophy
49
+
50
+ | Principle | Meaning |
51
+ |-----------|---------|
52
+ | **Silent by default** | The SDK never prints, raises, or disrupts the host application. Failures are reported to Agentverse and swallowed. |
53
+ | **Graceful degradation** | If init fails, the underlying framework still runs unpatched. A broken SDK must never break the user's agent. |
54
+ | **Single point of truth** | The agent URI encodes identity, Agentverse host, and optional log level. No env vars, config files, or scattered state. |
55
+ | **Wrapper, not framework** | The SDK wraps — it doesn't own the event loop, server, or application lifecycle. It hooks into Starlette lifespans and routes. |
56
+ | **Observability via events** | All errors, state transitions, and lifecycle signals are dispatched to Agentverse's Events API. Logging is developer-only (hidden unless `?log=LEVEL` is set on the URI). |
57
+
58
+ ---
59
+
60
+ ## Architecture
61
+
62
+ ```
63
+ ┌──────────────────────────────────────────────────────┐
64
+ │ User's Agent Application (LangGraph / A2A / ...) │
65
+ └────────────────────────┬─────────────────────────────┘
66
+ │ wraps
67
+ ┌────────────────────────▼─────────────────────────────┐
68
+ │ Adapter Module (langgraph/ or a2a/) │
69
+ │ - init() → parse URI, store _ctx │
70
+ │ - Application → register, add /av/chat route │
71
+ │ - _chat() → validate, ack, dispatch to bg │
72
+ │ - _process_bg() → call framework, convert, reply │
73
+ └────────────────────────┬─────────────────────────────┘
74
+ │ uses
75
+ ┌────────────────────────▼─────────────────────────────┐
76
+ │ _common/ │
77
+ │ - av.py → HTTP transport (register, send) │
78
+ │ - events.py → error handling decorators │
79
+ │ - starlette.py→ request parsing, lifespan wiring │
80
+ │ - types.py → AgentUri, AgentContext, events │
81
+ │ - config.py → shared constants │
82
+ │ - logger.py → dual-audience logging │
83
+ │ - helpers.py → utc_now() │
84
+ └──────────────────────────────────────────────────────┘
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Invariants
90
+
91
+ These must hold in every adapter. Violating any of them is a bug.
92
+
93
+ 1. **Init never raises.** URI parsing failure → `log_sdk` + return. Everything else → `handle_init_errors` (suppress + report).
94
+ 2. **`_ctx.agent is None` means init failed.** All downstream code must guard on this and fall through to unpatched behavior.
95
+ 3. **`_chat()` returns `200 {}` or raises `HTTPException`.** Validation failures (bad envelope, wrong target) raise `HTTPException` with an appropriate status code. Successful requests return `200 {}` immediately — all processing (ack, framework call, reply) happens in a `BackgroundTask`.
96
+ 4. **Every background error produces a reply.** The sender must always receive either a real reply or an error message — never silence. If sending the reply itself fails, push a `"user"` event instead (the sender cannot be reached, but the failure must still be visible on the agent dashboard).
97
+ 5. **Error handling is structural, not inline.** Decorators (`report_error_starlette`, `report_error_reply`) and context managers (`handle_init_errors`, `chat_error_on_fail`) own all error paths. Business logic never has bare try/except.
98
+ 6. **Error dispatch is self-guarded.** Any code that runs inside an `except` block and can itself fail must be wrapped in its own try/except. These are last-line-of-defense paths.
99
+ 7. **Content extraction is pure.** `content.py` modules raise on failure — they never catch, log, or dispatch. The calling decorator handles everything.
100
+ 8. **The user never sees SDK internals.** No prints, no stack traces, no log output unless developer logging is explicitly enabled.
101
+
102
+ ---
103
+
104
+ ## Request Processing Flow
105
+
106
+ Both adapters follow the same pipeline. Framework-specific steps are marked.
107
+
108
+ ```
109
+ Incoming POST /av/chat
110
+
111
+
112
+ ┌─ _chat() ──────────────────────────────────── @report_error_starlette ─┐
113
+ │ 1. Parse envelope from JSON body │
114
+ │ 2. Verify envelope signature (if enabled) │
115
+ │ 3. Validate target address matches this agent │
116
+ │ 4. Deserialize into ChatMessage or ChatAcknowledgement │
117
+ │ 5. If ChatAcknowledgement → return 200 {} (no-op) │
118
+ │ 6. Return 200 {} with BackgroundTask → _process_bg() │
119
+ └─────────────────────────────────────────────────────────────────────────┘
120
+
121
+
122
+ ┌─ _process_bg() ────────────────────────────── @report_error_reply ─────┐
123
+ │ 1. Send ChatAcknowledgement to sender │
124
+ │ 2. If message is StartSessionContent only → return (no-op) │
125
+ │ 3. Extract text from ChatMessage │
126
+ │ 4. Call framework: │
127
+ │ • LangGraph: POST /runs/wait via ASGI transport → single response │
128
+ │ • A2A: on_message_send_stream() → async event stream │
129
+ │ 5. Convert framework output to list[AgentContent]: │
130
+ │ • LangGraph: extract_ai_content(response_dict) │
131
+ │ • A2A: extract_content(event) per event │
132
+ │ 6. If no content produced → substitute DEFAULT_EMPTY_RESPONSE_TEXT │
133
+ │ 7. Send ChatMessage reply to sender │
134
+ └─────────────────────────────────────────────────────────────────────────┘
135
+ ```
136
+
137
+ ### Key Differences Between Adapters
138
+
139
+ | Aspect | LangGraph | A2A |
140
+ |--------|-----------|-----|
141
+ | Framework call | Single HTTP POST via ASGI transport | Async generator (streaming events) |
142
+ | Session handling | Maps session → LangGraph thread_id (uuid5 hash) | Maps session → A2A contextId |
143
+ | Reply cadence | One reply per request | One reply per content-bearing event |
144
+ | Empty fallback | In `_send_reply` via `content or [fallback]` | Triggered when `is_task_complete` and nothing was sent |
145
+ | Registration timing | During lifespan startup (env vars not ready at build time) | During `__init__` (server env is ready) |
146
+
147
+ ---
148
+
149
+ ## Error Handling
150
+
151
+ ### The Decorator Stack
152
+
153
+ ```
154
+ handle_init_errors(uri) → sync context manager, init phase
155
+ catches → dispatches event → suppresses
156
+
157
+ report_error_starlette(ctx) → async decorator, HTTP handlers
158
+ catches → dispatches event → re-raises as HTTPException(500)
159
+ (HTTPException passes through unchanged for custom HTTP errors)
160
+
161
+ report_error_reply(ctx) → async decorator, background processors
162
+ catches ChatProcessingError → dispatches event → sends error reply
163
+ catches Exception → dispatches event → sends generic error reply
164
+
165
+ chat_error_on_fail(msg) → async context manager, inside @report_error_reply
166
+ catches → raises ChatProcessingError (which the outer decorator handles)
167
+ ```
168
+
169
+ ### Error Flow Diagram
170
+
171
+ ```
172
+ Business logic raises
173
+
174
+ ├── Inside chat_error_on_fail?
175
+ │ └── Wraps as ChatProcessingError(custom_msg) → bubbles up
176
+
177
+
178
+ report_error_reply catches
179
+
180
+ ├── ChatProcessingError
181
+ │ ├── Has .exc? → dispatch exception event + send .reply_text to user
182
+ │ └── No .exc → dispatch message event + send .reply_text to user
183
+
184
+ └── Any other Exception
185
+ └── dispatch exception event + send DEFAULT_ERROR_REPLY to user
186
+ ```
187
+
188
+ ### `chat_error_on_fail` Categories
189
+
190
+ | Usage | `category` | `include_exc` | Rationale |
191
+ |-------|-----------|---------------|-----------|
192
+ | Sending ack/reply (network) | `"user"` | `False` | Network failures aren't system bugs; don't attach traceback to event |
193
+ | Parsing/extracting content | `"system"` | `True` (default) | SDK code failed; full traceback needed for debugging |
194
+
195
+ ---
196
+
197
+ ## Common Helpers Reference
198
+
199
+ ### `av.py` — Agentverse Transport
200
+
201
+ | Function | Purpose |
202
+ |----------|---------|
203
+ | `generate_agent_auth_token(identity)` | Create a signed attestation token valid for 2 minutes |
204
+ | `register_to_agentverse_sync(request, headers, config)` | Sync HTTP POST to register agent. Raises on failure (caller catches). |
205
+ | `send_message_to_agent(dest, msg, sender, ...)` | Resolve destination via Almanac, send envelope. Async. Raises on failure. |
206
+ | `set_agent_status(identity, active, config)` | Report online/offline to Almanac. Async. |
207
+ | `verify_envelope(envelope)` | Check signature. Returns False on any failure. User addresses always pass. |
208
+ | `_post_data(url, data, ...)` | Async httpx POST. Raises on non-2xx. |
209
+ | `_post_data_sync(url, data, ...)` | Sync requests POST. Raises on non-2xx. Used only for event dispatch. |
210
+
211
+ ### `events.py` — Error Handling Machinery
212
+
213
+ | Symbol | Purpose |
214
+ |--------|---------|
215
+ | `handle_init_errors(uri)` | Context manager: catch → report → suppress. For init and build phases. |
216
+ | `report_error(ctx, category, reraise)` | Base decorator: catch → dispatch event → optionally re-raise. |
217
+ | `report_error_starlette(ctx)` | HTTP decorator: report_error(reraise=True) + convert to 500. |
218
+ | `report_error_reply(ctx)` | Background decorator: catch → dispatch → send error reply to sender. |
219
+ | `chat_error_on_fail(msg, category, include_exc)` | Context manager: catch → raise ChatProcessingError. Use inside @report_error_reply. |
220
+ | `ChatProcessingError(msg, category, exc)` | Custom exception to control error reply text. Like HTTPException for background tasks. |
221
+ | `dispatch_event(agent, events)` | Sync POST to `/v1/events`. Raises on failure. |
222
+ | `dispatch_event_safe(agent, events)` | Same but swallows failures. Use in except blocks. |
223
+
224
+ ### `starlette.py` — HTTP Layer
225
+
226
+ | Function | Purpose |
227
+ |----------|---------|
228
+ | `parse_chat_message_from_request(request, verify, address)` | Validate envelope + deserialize to ChatMessage or ChatAcknowledgement. Raises HTTPException on any failure. |
229
+ | `setup_agent_status_lifespan(existing)` | Wrap an existing lifespan with start/stop status reporting. |
230
+ | `set_app_state(app, state)` | Attach AgentStarletteState to `app.state.agent`. |
231
+
232
+ ### `types.py` — Core Data Types
233
+
234
+ | Type | Role |
235
+ |------|------|
236
+ | `AgentUri` | Parsed URI: key, name, agentverse config, identity (cached). Frozen Pydantic model. |
237
+ | `AgentOptions` | Runtime options (`verify_envelope`, `track_interactions`). Pydantic model. |
238
+ | `AgentverseAgent` | Combines URI + profile + metadata + options. Pydantic model. |
239
+ | `AgentContext` | Mutable runtime state (dataclass). Holds `agent: AgentverseAgent | None`. |
240
+ | `AgentStarletteState` | Attached to app.state. Holds key + agentverse config. Dataclass with cached identity. |
241
+ | `AgentBatchEvents` | Event payload for `/v1/events`. Factory methods: `from_exception()`, `from_message()`. |
242
+
243
+ ### `config.py` — Constants
244
+
245
+ | Constant | Value | Purpose |
246
+ |----------|-------|---------|
247
+ | `DEFAULT_AGENTVERSE_CHAT_ENDPOINT` | `"/av/chat"` | Route path for incoming messages |
248
+ | `DEFAULT_HTTP_REQUESTS_TIMEOUT` | `10` (seconds) | Timeout for outbound HTTP calls |
249
+ | `AGENT_AUTH_TOKEN_VALIDITY` | `120` (seconds) | Token lifetime |
250
+ | `DEFAULT_EMPTY_RESPONSE_TEXT` | `"Agent returned no response."` | Fallback when framework produces no content |
251
+
252
+ By default, SDK agents register as **proxy agents** (`track_interactions=True` on `AgentOptions`): hub stores the chat URL as `redirect_url` and Almanac publishes `agentverse.proxy_endpoint`. Senders hit `/v2/agents/proxy/submit`, hub records `ProxyAgentInteractionEvent`, then redirects to the chat URL. Opt out with `AgentOptions(track_interactions=False)`.
253
+
254
+ ### `logger.py` — Logging
255
+
256
+ | Symbol | Purpose |
257
+ |--------|---------|
258
+ | `logger` | Standard Python logger (`"agentverse-sdk"`). Level CRITICAL by default (hidden). |
259
+ | `log_sdk(msg)` | Emits at level 99 (displays as WARNING). Always visible. Reserved for critical user-facing messages. |
260
+ | `configure(level)` | Enables developer logging at the given level. Called when URI has `?log=DEBUG`. |
261
+
262
+ ---
263
+
264
+ ## Implementing a New Adapter
265
+
266
+ Follow this checklist when adding support for a new framework:
267
+
268
+ ### 1. Module Structure
269
+
270
+ ```
271
+ agentverse_sdk/your_framework/
272
+ __init__.py # re-exports init(), Application class
273
+ _app.py # init(), Application class
274
+ config.py # Framework-specific constants (ports, URLs, timeouts)
275
+ content.py # Framework output → list[AgentContent] conversion
276
+ profile.py # Build RegistrationRequest from framework metadata
277
+ ```
278
+
279
+ ### 2. Required Components
280
+
281
+ ```python
282
+ from dataclasses import dataclass
283
+ from agentverse_sdk._common.types import AgentContext
284
+
285
+ # If you need extra state beyond AgentContext.agent:
286
+ @dataclass
287
+ class YourFrameworkContext(AgentContext):
288
+ config: YourConfig | None = None
289
+
290
+ _ctx = YourFrameworkContext()
291
+ ```
292
+
293
+ ### 3. `init(agent_uri_str, ...)` Function
294
+
295
+ ```python
296
+ def init(agent: str, *, profile=None, metadata=None, disable_message_auth=False):
297
+ # 1. Parse URI (outside handle_init_errors — report malformed URI via log_sdk)
298
+ try:
299
+ uri = AgentUri.from_str(agent)
300
+ except Exception as e:
301
+ log_sdk(FAILED_INIT_ERROR_FORMAT.format(f"malformed agent URI: {e}"))
302
+ return
303
+
304
+ # 2. Configure logging if URI has ?log=LEVEL
305
+ if uri.log_level is not None:
306
+ configure(uri.log_level)
307
+
308
+ # 3. Everything else inside handle_init_errors (suppresses + reports)
309
+ with handle_init_errors(uri):
310
+ _ctx.agent = AgentverseAgent(uri=uri, profile=profile, ...)
311
+ _ctx.config = YourConfig(...)
312
+ # Framework-specific patching/instrumentation
313
+ ```
314
+
315
+ ### 4. Application Class Pattern
316
+
317
+ ```python
318
+ class YourApplication:
319
+ def register(self):
320
+ # Build RegistrationRequest, call register_to_agentverse_sync
321
+ # Raises on failure — caller wraps in handle_init_errors
322
+ ...
323
+
324
+ def build(self) -> Starlette:
325
+ # Guard: if _ctx.agent is None or _ctx.config is None → return original app
326
+ # Wrap lifespan with setup_agent_status_lifespan
327
+ # Add POST /av/chat route → self._chat
328
+ # Attach AgentStarletteState via set_app_state
329
+ ...
330
+
331
+ @report_error_starlette(_ctx)
332
+ async def _chat(self, request: Request) -> Response:
333
+ # parse_chat_message_from_request → if ack, return 200
334
+ # return 200 with BackgroundTask → self._process_bg
335
+ ...
336
+
337
+ @report_error_reply(_ctx, "user")
338
+ async def _process_bg(self, env: Envelope, msg: ChatMessage):
339
+ # chat_error_on_fail("Failed to send ack") → send ack
340
+ # if StartSessionContent only → return
341
+ # chat_error_on_fail("Failed to parse...") → call framework + extract content
342
+ # chat_error_on_fail("Failed to send reply") → send reply (with empty fallback)
343
+ ...
344
+ ```
345
+
346
+ ### 5. Content Extraction (`content.py`)
347
+
348
+ - **Input**: Framework-specific response (dict, event stream, etc.) + `agent_uri: AgentUri`
349
+ - **Output**: `list[AgentContent]` (TextContent, ResourceContent)
350
+ - **Async**: Content functions are async (storage upload requires it).
351
+ - **Rules**:
352
+ - Raise on unrecoverable failure (the calling decorator handles it).
353
+ - Never drop data. Use data: URIs for binary, JSON serialization for structured data.
354
+ - Handle each content type with explicit isinstance/type checks.
355
+ - Return `[]` for genuinely empty responses (the adapter handles the fallback).
356
+ - For operations with graceful fallbacks (e.g. storage upload), use the `_safe`
357
+ variant of the helper (e.g. `upload_to_storage_safe`). The safe helper handles
358
+ logging and system event dispatch internally.
359
+
360
+ ---
361
+
362
+ ## Known Issues & Improvement Opportunities
363
+
364
+ ### Design Improvements to Consider
365
+
366
+ 1. **Extract common background processing** — Both adapters share identical logic for: send ack → check StartSession → [framework-specific] → send reply. The shared prefix/suffix could be a base class method or a helper function, with only the framework call as the varying step.
367
+
368
+ 2. **Testable Application classes** — Currently `_ctx` is a module-level global, making unit testing require module-level state manipulation. Consider accepting context as a constructor parameter (with module-level default) so tests can inject isolated state.
369
+
370
+ 3. **Content fallback in common** — Both adapters implement `content or [TextContent(text=DEFAULT_EMPTY_RESPONSE_TEXT)]` independently. This could be a shared `ensure_content(content: list[AgentContent]) -> list[AgentContent]` helper in common.
371
+
372
+ 4. **Rate limiting / backoff** — Event dispatch (`dispatch_event`) has no retry or backoff. If the Events API is temporarily down, events are silently lost. Consider a simple bounded queue with retry (similar to Sentry's telemetry buffer pattern).
373
+
374
+ 5. **Structured event metadata** — Currently errors are dispatched with just exception + traceback. Adding structured metadata (adapter name, framework version, message_id being processed) would improve Agentverse-side debugging.
375
+
376
+ ---
377
+
378
+ ## Logging & Events
379
+
380
+ ### Event Categories
381
+
382
+ | Category | Audience | Dashboard visibility |
383
+ |----------|----------|---------------------|
384
+ | `"system"` | Agentverse/SDK developers only | Internal monitoring — users never see these |
385
+ | `"user"` | End users | Visible on the user's agent dashboard |
386
+
387
+ Three entities produce or are affected by errors:
388
+
389
+ 1. **System** — the Agentverse platform and SDK infrastructure.
390
+ 2. **User** — the agent developer using Agentverse services.
391
+ 3. **Sender** — external agents interacting with the user's agent.
392
+
393
+ **Decision rule:** `"user"` events for anything related to the user or sender. Everything else is `"system"`.
394
+
395
+ **Use `"system"` events for:** infrastructure degradation the SDK handles gracefully (storage upload failures, transient service errors) and SDK bugs. These let the Agentverse team detect problems without requiring users to share logs. Users never see these.
396
+
397
+ **Use `"user"` events for:** errors caused by the user's own code (tool failures, unhandled exceptions in the framework) **and** errors originating from sender agents (malformed messages, invalid envelopes). Reporting sender-side errors gives the user a clear record of where the issue occurred, helping all parties diagnose problems faster.
398
+
399
+ ### Logging Channels
400
+
401
+ | Audience | API | Visibility | Use for |
402
+ |----------|-----|-----------|---------|
403
+ | End user | `log_sdk(msg)` | Always visible (level 99) | Init errors only: URI parse failures, events API unreachable during init |
404
+ | Developer | `logger.debug/info/error` | Hidden unless `?log=LEVEL` | Registration, sender addresses, dispatch outcomes |
405
+ | Agentverse team | `dispatch_event_safe(uri, event, "system")` | Internal dashboard | Graceful degradations, service health signals |
406
+
407
+ ### Graceful Degradation Pattern
408
+
409
+ When a non-critical operation fails but the SDK can continue with a fallback:
410
+
411
+ ```python
412
+ except Exception as e:
413
+ logger.error("Storage upload failed: %s", e)
414
+ dispatch_event_safe(
415
+ agent_uri,
416
+ AgentBatchEvents.from_exception(e, "", "system"),
417
+ )
418
+ # proceed with fallback (e.g. data: URI)
419
+ ```
420
+
421
+ This combination gives: developer logs for local debugging + system events for Agentverse-side monitoring — without requiring the user to do anything.
422
+
423
+ **Never log:**
424
+ - Raw Request objects (useless repr)
425
+ - Info the ASGI server already prints (method, path, status)
426
+ - Secrets, keys, or full URIs
427
+
428
+ **Always log:**
429
+ - What the SDK does that's invisible to the framework (registration, ack sent, reply dispatched)
430
+ - Error context inside except blocks (but only at `error` level)
@@ -0,0 +1,50 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentverse-sdk
3
+ Version: 0.1.0
4
+ Summary: Agentverse SDK — connect any AI agent framework to Agentverse
5
+ Project-URL: homepage, https://fetch.ai
6
+ Project-URL: repository, https://github.com/fetchai/agentverse
7
+ Author-email: "Fetch.ai" <developer@fetch.ai>
8
+ License: Apache 2.0
9
+ Requires-Python: <4.0,>=3.10
10
+ Requires-Dist: httpx<0.29.0,>=0.28.1
11
+ Requires-Dist: pydantic<3.0,>=2.8
12
+ Requires-Dist: requests<3.0,>=2.32.3
13
+ Requires-Dist: starlette<1.0,>=0.37.0
14
+ Requires-Dist: uagents-core<0.5.0,>=0.4.5
15
+ Provides-Extra: a2a
16
+ Requires-Dist: a2a-sdk<0.4.0,>=0.3.20; extra == 'a2a'
17
+ Provides-Extra: dev
18
+ Requires-Dist: pytest-asyncio<1,>=0.24; extra == 'dev'
19
+ Requires-Dist: pytest<9,>=8.0; extra == 'dev'
20
+ Requires-Dist: python-dotenv<2.0,>=1.0.0; extra == 'dev'
21
+ Requires-Dist: ruff<0.12,>=0.11.0; extra == 'dev'
22
+ Provides-Extra: langgraph
23
+ Requires-Dist: langgraph-api<1.0,>=0.2.0; (python_version >= '3.11') and extra == 'langgraph'
24
+ Requires-Dist: langgraph-cli<1.0,>=0.4.0; (python_version >= '3.11') and extra == 'langgraph'
25
+ Requires-Dist: python-dotenv<2.0,>=1.0.0; (python_version >= '3.11') and extra == 'langgraph'
26
+ Description-Content-Type: text/markdown
27
+
28
+ # agentverse-sdk
29
+
30
+ Connect any AI agent framework to [Agentverse](https://agentverse.ai) with a single `init()` call.
31
+
32
+ ## Installation
33
+
34
+ ```bash
35
+ # For A2A agents
36
+ pip install agentverse-sdk[a2a]
37
+
38
+ # For LangGraph agents
39
+ pip install agentverse-sdk[langgraph]
40
+ ```
41
+
42
+ ## Quick start
43
+
44
+ ```python
45
+ from agentverse_sdk.a2a import init
46
+
47
+ init("agentverse://your-agent-key@agentverse.ai/your-agent")
48
+ ```
49
+
50
+ See [DEVELOPER.md](DEVELOPER.md) for architecture and adapter implementation guide.
@@ -0,0 +1,23 @@
1
+ # agentverse-sdk
2
+
3
+ Connect any AI agent framework to [Agentverse](https://agentverse.ai) with a single `init()` call.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ # For A2A agents
9
+ pip install agentverse-sdk[a2a]
10
+
11
+ # For LangGraph agents
12
+ pip install agentverse-sdk[langgraph]
13
+ ```
14
+
15
+ ## Quick start
16
+
17
+ ```python
18
+ from agentverse_sdk.a2a import init
19
+
20
+ init("agentverse://your-agent-key@agentverse.ai/your-agent")
21
+ ```
22
+
23
+ See [DEVELOPER.md](DEVELOPER.md) for architecture and adapter implementation guide.
@@ -0,0 +1,3 @@
1
+ """Agentverse SDK — connect any AI agent framework to Agentverse."""
2
+
3
+ __version__ = "0.1.0"