dispatch_agents 0.13.3__tar.gz → 0.14.2__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.
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/PKG-INFO +1 -1
- dispatch_agents-0.14.2/README.md +182 -0
- dispatch_agents-0.14.2/RELEASE_NOTES.md +2 -0
- dispatch_agents-0.14.2/dispatch_agents/__init__.py +58 -0
- dispatch_agents-0.14.2/dispatch_agents/_deprecated_public_api.py +132 -0
- dispatch_agents-0.14.2/dispatch_agents/_internal/__init__.py +16 -0
- {dispatch_agents-0.13.3/dispatch_agents → dispatch_agents-0.14.2/dispatch_agents/_internal}/agent_service.py +0 -4
- dispatch_agents-0.14.2/dispatch_agents/_internal/bootstrap.py +11 -0
- dispatch_agents-0.14.2/dispatch_agents/_internal/config_validation.py +394 -0
- dispatch_agents-0.14.2/dispatch_agents/_internal/dev.py +90 -0
- dispatch_agents-0.14.2/dispatch_agents/_internal/dispatch.py +216 -0
- {dispatch_agents-0.13.3/dispatch_agents → dispatch_agents-0.14.2/dispatch_agents/_internal}/grpc_server.py +46 -50
- {dispatch_agents-0.13.3/dispatch_agents → dispatch_agents-0.14.2/dispatch_agents/_internal}/instrument.py +14 -18
- {dispatch_agents-0.13.3/dispatch_agents → dispatch_agents-0.14.2/dispatch_agents/_internal}/llm_langchain.py +11 -14
- {dispatch_agents-0.13.3/dispatch_agents → dispatch_agents-0.14.2/dispatch_agents/_internal}/models.py +45 -58
- {dispatch_agents-0.13.3/dispatch_agents → dispatch_agents-0.14.2/dispatch_agents/_internal}/proxy/server.py +91 -47
- dispatch_agents-0.14.2/dispatch_agents/_internal/transport.py +68 -0
- dispatch_agents-0.14.2/dispatch_agents/config.py +168 -0
- dispatch_agents-0.14.2/dispatch_agents/context.py +35 -0
- dispatch_agents-0.14.2/dispatch_agents/contrib/claude/__init__.py +169 -0
- dispatch_agents-0.14.2/dispatch_agents/contrib/openai/__init__.py +103 -0
- dispatch_agents-0.14.2/dispatch_agents/events.py +89 -0
- dispatch_agents-0.14.2/dispatch_agents/handlers.py +418 -0
- dispatch_agents-0.14.2/dispatch_agents/integrations/github/__init__.py +59 -0
- dispatch_agents-0.14.2/dispatch_agents/integrations/github/client.py +80 -0
- dispatch_agents-0.13.3/dispatch_agents/integrations/github/__init__.py → dispatch_agents-0.14.2/dispatch_agents/integrations/github/events.py +102 -169
- dispatch_agents-0.14.2/dispatch_agents/invocation.py +165 -0
- dispatch_agents-0.14.2/dispatch_agents/llm.py +822 -0
- dispatch_agents-0.13.3/dispatch_agents/logging_config.py → dispatch_agents-0.14.2/dispatch_agents/logging.py +45 -36
- dispatch_agents-0.14.2/dispatch_agents/mcp.py +439 -0
- dispatch_agents-0.14.2/dispatch_agents/memory.py +305 -0
- dispatch_agents-0.14.2/dispatch_agents/models.py +733 -0
- dispatch_agents-0.14.2/dispatch_agents/storage.py +35 -0
- dispatch_agents-0.14.2/examples/hello_world/README.md +65 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/hello_world/agent.py +16 -15
- dispatch_agents-0.14.2/examples/hello_world/test_agent.py +35 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/hello_world/uv.lock +1 -1
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/pyproject.toml +7 -3
- dispatch_agents-0.14.2/tests/conftest.py +20 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/e2e_claude_mcp_proxy.py +1 -1
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test.py +5 -4
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_agent_service.py +15 -15
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_agent_uid.py +1 -1
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_config.py +150 -22
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_contrib_claude.py +61 -10
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_contrib_openai.py +40 -16
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_dev_mode_isolation.py +51 -49
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_extra_headers.py +3 -7
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_fn_decorator.py +35 -13
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_github_client.py +25 -9
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_github_integration.py +21 -19
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_github_schema_compliance.py +1 -1
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_grpc_server.py +150 -64
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_init.py +59 -67
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_instrument.py +28 -11
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_llm_langchain.py +8 -8
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_llm_logging.py +30 -24
- dispatch_agents-0.14.2/tests/test_logging.py +178 -0
- dispatch_agents-0.14.2/tests/test_mcp.py +399 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_proxy_e2e.py +4 -4
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_proxy_server.py +187 -119
- dispatch_agents-0.14.2/tests/test_public_api.py +411 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_resources.py +1 -1
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_sse_utils.py +2 -2
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_trace_context.py +14 -10
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_typed_events.py +57 -20
- dispatch_agents-0.14.2/tests/typing_checks.py +65 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/uv.lock +7 -7
- dispatch_agents-0.13.3/README.md +0 -48
- dispatch_agents-0.13.3/RELEASE_NOTES.md +0 -2
- dispatch_agents-0.13.3/dispatch_agents/__init__.py +0 -288
- dispatch_agents-0.13.3/dispatch_agents/config.py +0 -767
- dispatch_agents-0.13.3/dispatch_agents/contrib/claude/__init__.py +0 -246
- dispatch_agents-0.13.3/dispatch_agents/contrib/openai/__init__.py +0 -167
- dispatch_agents-0.13.3/dispatch_agents/events.py +0 -986
- dispatch_agents-0.13.3/dispatch_agents/integrations/github/client.py +0 -121
- dispatch_agents-0.13.3/dispatch_agents/invocation.py +0 -25
- dispatch_agents-0.13.3/dispatch_agents/llm.py +0 -1027
- dispatch_agents-0.13.3/dispatch_agents/mcp.py +0 -266
- dispatch_agents-0.13.3/dispatch_agents/memory.py +0 -286
- dispatch_agents-0.13.3/dispatch_agents/resources.py +0 -68
- dispatch_agents-0.13.3/examples/hello_world/test_agent.py +0 -45
- dispatch_agents-0.13.3/tests/test_logging_config.py +0 -147
- dispatch_agents-0.13.3/tests/test_mcp.py +0 -207
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/.claude-plugin/marketplace.json +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/.github/scripts/change_scope.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/.github/scripts/ci_git.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/.github/scripts/version_policy.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/.github/tests/test_change_scope.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/.github/tests/test_ci_git.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/.github/tests/test_version_policy.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/.github/workflows/ci-reusable.yml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/.github/workflows/feature-branch.yml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/.github/workflows/release.yml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/.github/workflows/version-policy-reusable.yml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/.gitignore +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/CONTRIBUTING.md +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/LICENSE +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/LICENSE-3rdparty.csv +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/NOTICE +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/agentservice/__init__.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/agentservice/py.typed +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/agentservice/v1/__init__.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/agentservice/v1/message_pb2.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/agentservice/v1/message_pb2.pyi +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/agentservice/v1/message_pb2_grpc.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/agentservice/v1/request_response_pb2.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/agentservice/v1/request_response_pb2.pyi +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/agentservice/v1/request_response_pb2_grpc.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/agentservice/v1/service_pb2.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/agentservice/v1/service_pb2.pyi +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/agentservice/v1/service_pb2_grpc.py +0 -0
- {dispatch_agents-0.13.3/dispatch_agents → dispatch_agents-0.14.2/dispatch_agents/_internal}/proxy/__init__.py +0 -0
- {dispatch_agents-0.13.3/dispatch_agents → dispatch_agents-0.14.2/dispatch_agents/_internal}/proxy/sse_utils.py +0 -0
- {dispatch_agents-0.13.3/dispatch_agents → dispatch_agents-0.14.2/dispatch_agents/_internal}/version.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/dispatch_agents/contrib/__init__.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/dispatch_agents/integrations/__init__.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/dispatch_agents/integrations/github/README.md +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/dispatch_agents/py.typed +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/README.md +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/company-researcher/.gitignore +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/company-researcher/AGENTS.md +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/company-researcher/README.md +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/company-researcher/agent.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/company-researcher/dispatch.yaml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/company-researcher/pyproject.toml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/company-researcher/uv.lock +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/conversational-agent/README.md +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/conversational-agent/agent.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/conversational-agent/dispatch.yaml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/conversational-agent/pyproject.toml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/daily-digest/README.md +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/daily-digest/agent.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/daily-digest/dispatch.yaml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/daily-digest/pyproject.toml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/deep-research/README.md +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/deep-research/agent.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/deep-research/configuration.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/deep-research/deep_researcher.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/deep-research/dispatch.yaml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/deep-research/prompts.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/deep-research/pyproject.toml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/deep-research/state.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/deep-research/tools.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/hello_world/.gitignore +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/hello_world/AGENTS.md +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/hello_world/dispatch.yaml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/hello_world/pyproject.toml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/knowledge-base-query/.env.example +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/knowledge-base-query/.gitignore +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/knowledge-base-query/AGENTS.md +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/knowledge-base-query/agent.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/knowledge-base-query/dispatch.yaml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/knowledge-base-query/pyproject.toml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/multi-framework/README.md +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/multi-framework/agent.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/multi-framework/dispatch.yaml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/multi-framework/pyproject.toml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/pyproject.toml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/uv.lock +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/weather-assistant/.gitignore +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/weather-assistant/AGENTS.md +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/weather-assistant/agent.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/weather-assistant/dispatch.yaml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/weather-assistant/pyproject.toml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/weather-assistant/uv.lock +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/weather-service/.gitignore +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/weather-service/AGENTS.md +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/weather-service/agent.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/weather-service/dispatch.yaml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/weather-service/pyproject.toml +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/examples/weather-service/uv.lock +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/internal/py.typed +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/plugins/README.md +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/__init__.py +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/schemas/README.md +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/schemas/octokit-webhooks.json +0 -0
- {dispatch_agents-0.13.3 → dispatch_agents-0.14.2}/tests/test_memory.py +0 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Dispatch Agents SDK
|
|
2
|
+
|
|
3
|
+
Build and deploy event-driven AI agents with simple Python decorators.
|
|
4
|
+
[dispatchagents.ai](https://dispatchagents.ai/) — currently in public preview.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
uv add git+ssh://git@github.com/datadog-labs/dispatch_agents_sdk.git@vX.Y.Z
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Replace `vX.Y.Z` with the latest tag:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
git ls-remote --tags git@github.com:datadog-labs/dispatch_agents_sdk.git 'v*' \
|
|
16
|
+
| sort -t'/' -k3 -V | tail -1 | awk -F'/' '{print $3}'
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Core Concepts
|
|
20
|
+
|
|
21
|
+
### `@on` — Subscribe to events
|
|
22
|
+
|
|
23
|
+
Handle events published to a topic. The payload is automatically validated
|
|
24
|
+
against your Pydantic model before your handler is called.
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from dispatch_agents import BasePayload, on
|
|
28
|
+
|
|
29
|
+
class OrderPayload(BasePayload):
|
|
30
|
+
order_id: str
|
|
31
|
+
customer_email: str
|
|
32
|
+
|
|
33
|
+
class OrderResult(BasePayload):
|
|
34
|
+
status: str
|
|
35
|
+
|
|
36
|
+
@on(topic="orders.process")
|
|
37
|
+
async def process_order(payload: OrderPayload) -> OrderResult:
|
|
38
|
+
await send_confirmation(payload.customer_email, payload.order_id)
|
|
39
|
+
return OrderResult(status="confirmed")
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Subscribe to GitHub events by passing a GitHub event class:
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from dispatch_agents import on
|
|
46
|
+
from dispatch_agents.integrations.github.events import PullRequestOpened
|
|
47
|
+
|
|
48
|
+
@on(github_event=PullRequestOpened)
|
|
49
|
+
async def handle_pr(payload: PullRequestOpened) -> None:
|
|
50
|
+
print(f"PR opened: {payload.pull_request.title}")
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### `@fn` — Expose a callable function
|
|
54
|
+
|
|
55
|
+
Register a function that other agents can call directly by name using `invoke()`.
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from dispatch_agents import BasePayload, fn
|
|
59
|
+
|
|
60
|
+
class WeatherRequest(BasePayload):
|
|
61
|
+
city: str
|
|
62
|
+
|
|
63
|
+
class WeatherResponse(BasePayload):
|
|
64
|
+
temperature: float
|
|
65
|
+
conditions: str
|
|
66
|
+
|
|
67
|
+
@fn()
|
|
68
|
+
async def get_weather(request: WeatherRequest) -> WeatherResponse:
|
|
69
|
+
data = await fetch_weather_api(request.city)
|
|
70
|
+
return WeatherResponse(temperature=data["temp"], conditions=data["sky"])
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### `@init` — One-time async setup
|
|
74
|
+
|
|
75
|
+
Runs once before any events are processed. Use for connecting to databases,
|
|
76
|
+
loading models, or initializing shared state.
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from dispatch_agents import BasePayload, init, on
|
|
80
|
+
|
|
81
|
+
_client = None
|
|
82
|
+
|
|
83
|
+
@init
|
|
84
|
+
async def setup():
|
|
85
|
+
global _client
|
|
86
|
+
_client = await connect_to_database()
|
|
87
|
+
|
|
88
|
+
class QueryPayload(BasePayload):
|
|
89
|
+
user_id: str
|
|
90
|
+
|
|
91
|
+
@on(topic="users.query")
|
|
92
|
+
async def query_users(payload: QueryPayload) -> QueryResult:
|
|
93
|
+
rows = await _client.fetch(
|
|
94
|
+
"select * from users where id = $1",
|
|
95
|
+
payload.user_id,
|
|
96
|
+
)
|
|
97
|
+
return QueryResult(rows=rows)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### `emit_event` — Fire-and-forget publishing
|
|
101
|
+
|
|
102
|
+
Publish an event without waiting for handlers to process it.
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from dispatch_agents import emit_event, on
|
|
106
|
+
|
|
107
|
+
@on(topic="orders.process")
|
|
108
|
+
async def process_order(payload: OrderPayload) -> OrderResult:
|
|
109
|
+
await fulfill(payload)
|
|
110
|
+
# Notify other agents — returns immediately
|
|
111
|
+
await emit_event("notifications.send", {"email": payload.customer_email})
|
|
112
|
+
return OrderResult(status="fulfilled")
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### `invoke` — Call another agent directly
|
|
116
|
+
|
|
117
|
+
Call a `@fn`-decorated function on another agent and wait for the result.
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from dispatch_agents import invoke, on
|
|
121
|
+
|
|
122
|
+
@on(topic="reports.request")
|
|
123
|
+
async def handle_report(payload: ReportPayload) -> ReportResult:
|
|
124
|
+
weather = await invoke(
|
|
125
|
+
agent_name="weather-service",
|
|
126
|
+
function_name="get_weather",
|
|
127
|
+
payload={"city": payload.city},
|
|
128
|
+
response_model=WeatherResponse,
|
|
129
|
+
timeout=30.0,
|
|
130
|
+
)
|
|
131
|
+
return ReportResult(weather=weather.conditions)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Error Handling
|
|
135
|
+
|
|
136
|
+
- **`OSError` and subclasses** → automatic retry with exponential backoff
|
|
137
|
+
- **`ValueError` and subclasses** → terminal failure, not retried
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from dispatch_agents import on
|
|
141
|
+
|
|
142
|
+
@on(topic="data.fetch")
|
|
143
|
+
async def fetch(payload: FetchPayload) -> FetchResult:
|
|
144
|
+
if not payload.url.startswith("https://"):
|
|
145
|
+
raise ValueError("Only HTTPS URLs allowed") # not retried
|
|
146
|
+
|
|
147
|
+
# TimeoutError (an OSError subclass) will be retried automatically
|
|
148
|
+
response = await httpx_client.get(payload.url, timeout=10.0)
|
|
149
|
+
return FetchResult(data=response.json())
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Payloads
|
|
153
|
+
|
|
154
|
+
All handler inputs and outputs must inherit from `BasePayload`:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from dispatch_agents import BasePayload
|
|
158
|
+
from typing import Optional
|
|
159
|
+
|
|
160
|
+
class TaskPayload(BasePayload):
|
|
161
|
+
task_id: str
|
|
162
|
+
priority: int = 1
|
|
163
|
+
tags: list[str] = []
|
|
164
|
+
metadata: Optional[dict[str, str]] = None
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Examples
|
|
168
|
+
|
|
169
|
+
- [`hello_world`](../examples/hello_world/) — typed payloads, error handling, persistent storage
|
|
170
|
+
- [`weather-service`](../examples/weather-service/) + [`weather-assistant`](../examples/weather-assistant/) — inter-agent `invoke()`
|
|
171
|
+
- [`conversational-agent`](../examples/conversational-agent/) — multi-turn LLM chat with memory
|
|
172
|
+
- [`daily-digest`](../examples/daily-digest/) — scheduled agents
|
|
173
|
+
- [`deep-research`](../examples/deep-research/) — parallel supervisor/researcher pattern
|
|
174
|
+
- [`multi-framework`](../examples/multi-framework/) — Claude SDK, OpenAI Agents, LangGraph
|
|
175
|
+
|
|
176
|
+
## Full Documentation
|
|
177
|
+
|
|
178
|
+
[dispatchagents.ai/docs/sdk](https://dispatchagents.ai/docs/sdk)
|
|
179
|
+
|
|
180
|
+
## Support
|
|
181
|
+
|
|
182
|
+
GitHub Issues: [github.com/datadog-labs/dispatch_agents_sdk/issues](https://github.com/datadog-labs/dispatch_agents_sdk/issues)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Dispatch Agents Python SDK.
|
|
2
|
+
|
|
3
|
+
The root package re-exports the most common agent APIs for convenience:
|
|
4
|
+
|
|
5
|
+
* ``on``, ``fn``, and ``init`` from :mod:`dispatch_agents.handlers`
|
|
6
|
+
* ``emit_event`` from :mod:`dispatch_agents.events`
|
|
7
|
+
* ``invoke`` from :mod:`dispatch_agents.invocation`
|
|
8
|
+
* ``get_data_dir`` from :mod:`dispatch_agents.storage`
|
|
9
|
+
* ``get_mcp_client`` and ``get_mcp_servers_config`` from :mod:`dispatch_agents.mcp`
|
|
10
|
+
* ``config``, ``memory``, ``llm``, ``context``, and ``models`` as public modules
|
|
11
|
+
|
|
12
|
+
For canonical API ownership, browse the public submodules below.
|
|
13
|
+
Deprecated compatibility aliases from earlier SDK versions remain importable
|
|
14
|
+
from the root package, but new code should import them from their canonical
|
|
15
|
+
public submodules.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
from ._deprecated_public_api import install_deprecated_public_aliases
|
|
21
|
+
from ._internal.bootstrap import install_proto_import_path
|
|
22
|
+
from ._internal.dev import install_dev_mode_audit_hook
|
|
23
|
+
|
|
24
|
+
install_proto_import_path()
|
|
25
|
+
|
|
26
|
+
from . import context, llm, models
|
|
27
|
+
from .config import config
|
|
28
|
+
from .events import emit_event
|
|
29
|
+
from .handlers import fn, init, on
|
|
30
|
+
from .invocation import invoke
|
|
31
|
+
from .llm import extra_headers
|
|
32
|
+
from .mcp import get_mcp_client, get_mcp_servers_config
|
|
33
|
+
from .memory import memory
|
|
34
|
+
from .models import BasePayload, McpHttpServerConfig
|
|
35
|
+
from .storage import DisallowedWriteError, get_data_dir
|
|
36
|
+
|
|
37
|
+
__all__ = [
|
|
38
|
+
"BasePayload",
|
|
39
|
+
"config",
|
|
40
|
+
"context",
|
|
41
|
+
"DisallowedWriteError",
|
|
42
|
+
"emit_event",
|
|
43
|
+
"extra_headers",
|
|
44
|
+
"fn",
|
|
45
|
+
"get_data_dir",
|
|
46
|
+
"get_mcp_client",
|
|
47
|
+
"get_mcp_servers_config",
|
|
48
|
+
"init",
|
|
49
|
+
"invoke",
|
|
50
|
+
"llm",
|
|
51
|
+
"McpHttpServerConfig",
|
|
52
|
+
"memory",
|
|
53
|
+
"models",
|
|
54
|
+
"on",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
install_deprecated_public_aliases()
|
|
58
|
+
install_dev_mode_audit_hook()
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"""Deprecated public compatibility aliases.
|
|
2
|
+
|
|
3
|
+
This module is the single cleanup point for old public import paths that still
|
|
4
|
+
have a current public owner. Do not add aliases that point to ``_internal``.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import warnings
|
|
10
|
+
from importlib import import_module
|
|
11
|
+
from types import ModuleType
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
AliasTargets = dict[str, str]
|
|
15
|
+
|
|
16
|
+
_STATIC_ALIASES: dict[str, AliasTargets] = {
|
|
17
|
+
"dispatch_agents": {
|
|
18
|
+
"HandlerMetadata": "dispatch_agents.models",
|
|
19
|
+
"InvocationStatus": "dispatch_agents.models",
|
|
20
|
+
"KVGetResponse": "dispatch_agents.models",
|
|
21
|
+
"KVListResponse": "dispatch_agents.models",
|
|
22
|
+
"KVMemoryRecord": "dispatch_agents.models",
|
|
23
|
+
"LLMFunctionCall": "dispatch_agents.models",
|
|
24
|
+
"LLMToolCall": "dispatch_agents.models",
|
|
25
|
+
"MemoryClient": "dispatch_agents.memory",
|
|
26
|
+
"MemoryWriteResponse": "dispatch_agents.models",
|
|
27
|
+
"SessionGetResponse": "dispatch_agents.models",
|
|
28
|
+
"get_extra_llm_headers": "dispatch_agents.llm",
|
|
29
|
+
"get_handler_metadata": "dispatch_agents.handlers",
|
|
30
|
+
"get_handler_schemas": "dispatch_agents.handlers",
|
|
31
|
+
},
|
|
32
|
+
"dispatch_agents.config": {
|
|
33
|
+
"DispatchConfig": "dispatch_agents.models",
|
|
34
|
+
"DomainSelector": "dispatch_agents.models",
|
|
35
|
+
"EgressConfig": "dispatch_agents.models",
|
|
36
|
+
"MCPServerConfig": "dispatch_agents.models",
|
|
37
|
+
"NetworkConfig": "dispatch_agents.models",
|
|
38
|
+
"ResourceConfig": "dispatch_agents.models",
|
|
39
|
+
"ResourceLimits": "dispatch_agents.models",
|
|
40
|
+
"SecretConfig": "dispatch_agents.models",
|
|
41
|
+
"VolumeConfig": "dispatch_agents.models",
|
|
42
|
+
"VolumeMode": "dispatch_agents.models",
|
|
43
|
+
},
|
|
44
|
+
"dispatch_agents.events": {
|
|
45
|
+
"BasePayload": "dispatch_agents.models",
|
|
46
|
+
"HandlerMetadata": "dispatch_agents.models",
|
|
47
|
+
"fn": "dispatch_agents.handlers",
|
|
48
|
+
"get_handler_metadata": "dispatch_agents.handlers",
|
|
49
|
+
"get_handler_schemas": "dispatch_agents.handlers",
|
|
50
|
+
"init": "dispatch_agents.handlers",
|
|
51
|
+
"invoke": "dispatch_agents.invocation",
|
|
52
|
+
"on": "dispatch_agents.handlers",
|
|
53
|
+
},
|
|
54
|
+
"dispatch_agents.integrations.github.client": {
|
|
55
|
+
"GitHubAppToken": "dispatch_agents.models",
|
|
56
|
+
},
|
|
57
|
+
"dispatch_agents.invocation": {
|
|
58
|
+
"InvocationStatus": "dispatch_agents.models",
|
|
59
|
+
},
|
|
60
|
+
"dispatch_agents.llm": {
|
|
61
|
+
"LLMFunctionCall": "dispatch_agents.models",
|
|
62
|
+
"LLMMessage": "dispatch_agents.models",
|
|
63
|
+
"LLMResponse": "dispatch_agents.models",
|
|
64
|
+
"LLMToolCall": "dispatch_agents.models",
|
|
65
|
+
},
|
|
66
|
+
"dispatch_agents.mcp": {
|
|
67
|
+
"McpHttpServerConfig": "dispatch_agents.models",
|
|
68
|
+
},
|
|
69
|
+
"dispatch_agents.memory": {
|
|
70
|
+
"KVGetResponse": "dispatch_agents.models",
|
|
71
|
+
"KVListResponse": "dispatch_agents.models",
|
|
72
|
+
"MemoryWriteResponse": "dispatch_agents.models",
|
|
73
|
+
"SessionGetResponse": "dispatch_agents.models",
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# Alias maps keyed by module name, populated by ``install_deprecated_public_aliases``.
|
|
79
|
+
# Held here rather than as a dynamic attribute on each patched module so the lookup
|
|
80
|
+
# stays fully typed (``ModuleType`` has no such attribute slot).
|
|
81
|
+
_INSTALLED_ALIASES: dict[str, AliasTargets] = {}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class _DeprecatedAliasModule(ModuleType):
|
|
85
|
+
def __getattribute__(self, name: str) -> object:
|
|
86
|
+
module_name = ModuleType.__getattribute__(self, "__name__")
|
|
87
|
+
target_module = _INSTALLED_ALIASES.get(module_name, {}).get(name)
|
|
88
|
+
if target_module is not None:
|
|
89
|
+
return _resolve_deprecated_alias(module_name, name, target_module)
|
|
90
|
+
return ModuleType.__getattribute__(self, name)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def install_deprecated_public_aliases() -> None:
|
|
94
|
+
"""Install all deprecated public import aliases."""
|
|
95
|
+
for module_name, aliases in _all_aliases().items():
|
|
96
|
+
module = import_module(module_name)
|
|
97
|
+
_INSTALLED_ALIASES[module_name] = dict(aliases)
|
|
98
|
+
module.__class__ = _DeprecatedAliasModule
|
|
99
|
+
_extend_all(module, aliases)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _all_aliases() -> dict[str, AliasTargets]:
|
|
103
|
+
aliases = {module: dict(names) for module, names in _STATIC_ALIASES.items()}
|
|
104
|
+
github_events = import_module("dispatch_agents.integrations.github.events")
|
|
105
|
+
aliases["dispatch_agents.integrations.github"] = {
|
|
106
|
+
name: "dispatch_agents.integrations.github.events"
|
|
107
|
+
for name in github_events.__all__
|
|
108
|
+
if name != "GitHubAppToken"
|
|
109
|
+
}
|
|
110
|
+
return aliases
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _resolve_deprecated_alias(
|
|
114
|
+
module_name: str,
|
|
115
|
+
name: str,
|
|
116
|
+
target_module: str,
|
|
117
|
+
) -> Any:
|
|
118
|
+
warnings.warn(
|
|
119
|
+
f"{module_name}.{name} is deprecated; use {target_module}.{name} instead.",
|
|
120
|
+
FutureWarning,
|
|
121
|
+
stacklevel=3,
|
|
122
|
+
)
|
|
123
|
+
return getattr(import_module(target_module), name)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _extend_all(module: ModuleType, aliases: AliasTargets) -> None:
|
|
127
|
+
all_names = getattr(module, "__all__", None)
|
|
128
|
+
if not isinstance(all_names, list):
|
|
129
|
+
return
|
|
130
|
+
for name in aliases:
|
|
131
|
+
if name not in all_names:
|
|
132
|
+
all_names.append(name)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Internal implementation packages for Dispatch Agents.
|
|
2
|
+
|
|
3
|
+
Anything under this package is private to the SDK implementation and carries no
|
|
4
|
+
backwards-compatibility guarantee. The public surface is the top-level
|
|
5
|
+
``dispatch_agents`` package and its documented modules.
|
|
6
|
+
|
|
7
|
+
Import policy:
|
|
8
|
+
|
|
9
|
+
- First-party packages in this monorepo (``backend``, ``cli``) MAY import from
|
|
10
|
+
``dispatch_agents._internal``. They version-lock with the SDK and share its
|
|
11
|
+
internal wire/orchestration contracts; this coupling is deliberate, not a leak.
|
|
12
|
+
- External agent code MUST NOT import from ``_internal``. Use the public surface
|
|
13
|
+
(``dispatch_agents`` and ``dispatch_agents.models``). The ``examples/`` agents
|
|
14
|
+
serve as the proxy for external usage and are guarded by a test that forbids
|
|
15
|
+
any ``_internal`` import there.
|
|
16
|
+
"""
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""SDK import-time bootstrap helpers."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def install_proto_import_path() -> None:
|
|
8
|
+
"""Add the SDK root so generated protobuf packages can be imported."""
|
|
9
|
+
sdk_root = str(Path(__file__).parents[2])
|
|
10
|
+
if sdk_root not in sys.path:
|
|
11
|
+
sys.path.insert(0, sdk_root)
|