Python SDK for DAF (Declarative Agentic Framework) — thin MCP client
Project description
tai-daf-sdk
Python SDK for DAF — Declarative Agentic Framework. Thin, MCP-native client. Every call goes to the same MCP tool the backend exposes at /mcp — no separate REST surface to keep in sync, no per-resource wrappers to hand-write.
PyPI: https://pypi.org/project/tai-daf-sdk/
Install
Alpha channel while the surface stabilises:
pip install --pre tai-daf-sdk
Python ≥ 3.10.
30-second quickstart
from tai_daf_sdk import DAF
with DAF(
base_url="https://daf-sdk-backend-dev.azurewebsites.net",
api_key="daf_...",
) as client:
# List LLM endpoints on your account
endpoints = client.llm_endpoints.list()
ep_id = endpoints["endpoints"][0]["id"]
# Create an agent bound to that endpoint
agent = client.agents.create(
name="my-assistant",
system_instructions="You answer politely.",
llm_endpoint_id=ep_id,
confirm=True,
)
print("Created:", agent["created"]["id"])
Async version
Same API, async prefix, always inside async with:
import asyncio
from tai_daf_sdk import AsyncDAF
async def main():
async with AsyncDAF(base_url="...", api_key="daf_...") as client:
agents = await client.agents.list()
for a in agents["agents"]:
print(a["id"], a["name"])
asyncio.run(main())
How the dispatch works
The SDK is a thin dispatch layer over MCP tools. client.<resource>.<method>(**kwargs) maps to daf_<method>_<resource>:
| Python call | MCP tool |
|---|---|
client.agents.list() |
daf_list_agents |
client.agents.create(...) |
daf_create_agent (singular fallback) |
client.agents.describe(name_or_id=...) |
daf_describe_agent |
client.agents.update(agent_id=..., patch=...) |
daf_update_agent |
client.agents.delete(agent_id=..., confirm=True) |
daf_delete_agent |
client.swarms.list() |
daf_list_swarms |
client.llm_endpoints.list() |
daf_list_llm_endpoints |
Singular fallback. Every collection is plural on the SDK (client.agents, client.swarms) so it reads naturally. When you call .create() the SDK first tries daf_create_agents (plural), and if that's not registered, falls back to daf_create_agent (singular). This matches the backend's real naming — list ops are plural, per-item ops are singular.
Escape hatch for irregular tool names. A handful of tools don't fit daf_<method>_<resource> — like daf_attach_guardrail_to_agent, daf_run_tool, daf_mcp_health_check, daf_export_agent, daf_import_agent, daf_list_node_types. Use client.call(tool_name, args_dict):
result = client.call(
"daf_attach_guardrail_to_agent",
{"agent_id": agent_id, "guardrail_id": gid, "confirm": True},
)
Async client has the same escape hatch:
result = await async_client.call("daf_attach_guardrail_to_agent", {...})
Errors
The SDK maps the backend's structured error codes to typed exceptions:
| Backend code | Exception |
|---|---|
VALIDATION_ERROR |
BadRequestError |
ENTITY_NOT_FOUND |
NotFoundError |
FORBIDDEN |
PermissionError |
NAME_TAKEN / DUPLICATE_URL |
ConflictError |
QUOTA_EXCEEDED |
RateLimitError |
| Others | APIError (base class) |
from tai_daf_sdk.exceptions import BadRequestError
try:
client.agents.create(name="broken", model_provider="azure", confirm=True)
except BadRequestError as exc:
print(f"Invalid config: {exc}")
ConnectionError is raised for transport failures (backend unreachable, DNS, TLS).
Configuration
Constructor accepts:
base_url(str) — DAF backend URL. Local dev =http://localhost:8012, dev cloud =https://daf-sdk-backend-dev.azurewebsites.net.api_key(str) — DAF API key (starts withdaf_). Get one from Settings → API keys in the webapp.token(str) — Bearer JWT alternative to API key. Only one ofapi_key/tokenat a time.timeout(float, default 60.0) — HTTP timeout in seconds.
Alternatively, set DAF_MCP_STDIO_COMMAND to run the SDK against a local stdio MCP server instead of HTTP.
Streaming
For tools whose backend implementation streams SSE events (daf_start_workflow, daf_subscribe_workflow), use client.stream(tool_name, args):
for event in client.stream("daf_subscribe_workflow", {"run_id": run_id}):
if event.get("event") == "output_node":
print(event["data"]["content"], end="", flush=True)
Async equivalent iterates via async for:
async for event in async_client.stream("daf_subscribe_workflow", {"run_id": run_id}):
...
Full guide + more examples
- Guide: docs/GUIDE.md — every capability with working code.
- Examples:
examples/— runnable scripts:01_hello_agent.py— create + describe + delete an agent02_swarm_workflow.py— compose a two-agent swarm via workflow drafts03_triggers.py— webhook + cron + event triggers04_memory.py— per-agent memory + shared memory05_guardrails.py— attach a guardrail to an agent06_streaming.py— subscribe to workflow SSE events
Each example is self-contained. Pass --url and --api-key (or set DAF_MCP_URL / DAF_API_KEY env vars).
Regenerating from your backend's catalog
When the backend adds tools, the SDK's tool registry catches up automatically:
python -m tai_daf_sdk.codegen \
--mcp-url https://daf-sdk-backend-dev.azurewebsites.net \
--api-key daf_... \
--out tai_daf_sdk/
Regenerates:
_tool_registry.py— MCP tool → resource+method maptypes.py— TypedDict per tool inputclient.pyi— IDE stubs for autocompletemodels.py— Pydantic wrappers where declared
The CI workflow .github/workflows/mcp-catalog-sync.yml runs this on schedule and fails when the shipped registry drifts from the live backend catalog.
End-to-end test scenarios
scripts/sdk_tests/ — 45 scripts (24 customer sandbox stories + 21 read-only sweeps) verify the whole surface against a live backend. Same story IDs as the MCP-side suite in daf-sdk-backend/scripts/mcp_tests so you can cross-check SDK ↔ MCP agree on the customer contract.
python -m scripts.sdk_tests.run_all \
--url https://daf-sdk-backend-dev.azurewebsites.net \
--api-key daf_...
Filter with --set 1|2 or --filter us_01 for one scenario at a time.
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tai_daf_sdk-2.0.0a3.tar.gz.
File metadata
- Download URL: tai_daf_sdk-2.0.0a3.tar.gz
- Upload date:
- Size: 37.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
14b5fe6904069eefb9c518019ea6a6bd4611437b1af4c90571fd4dde4ac3fd26
|
|
| MD5 |
b24f656667a5030c5ef9d92eb30aa0e4
|
|
| BLAKE2b-256 |
da44bf43f0eadbffbfb1c7c6bfaf36586ea6b5068cb8eba28d0caae0baa4b472
|
File details
Details for the file tai_daf_sdk-2.0.0a3-py3-none-any.whl.
File metadata
- Download URL: tai_daf_sdk-2.0.0a3-py3-none-any.whl
- Upload date:
- Size: 29.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e24e56e819be4225285a4aa892b3a206f93162b7fbcab2dbc9950a967c14053e
|
|
| MD5 |
ba0066d907ec2b7f00523e8ee547bd3a
|
|
| BLAKE2b-256 |
ae864c81024a0d85b5b4cac0b7ca9c13ccc739774763dfb153fa8536ce9a1067
|