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.
Metadata
Release files for tai-daf-sdk 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tai_daf_sdk-2.0.0.tar.gz | 31.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tai_daf_sdk-2.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 61.6 kB
Release files / tai_daf_sdk-2.0.0.tar.gz
| Download URL | tai_daf_sdk-2.0.0.tar.gz |
|---|---|
| Size | 31.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a984f1f04417b4cb23b00edb27cc1a80739bb934715774abec6fbc5c9b7b4446
|
|
BLAKE2b-256 checksum How to use checksums |
06215b8a5d0f0e8a4bb319c1d562eff43d52a3e2c2a3c128a29d696ffd702849
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|
Release files / tai_daf_sdk-2.0.0-py3-none-any.whl
| Download URL | tai_daf_sdk-2.0.0-py3-none-any.whl |
|---|---|
| Size | 30.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e6823b426e60e4c5ff45dcf52fb6ee8d46e1b0912c93a2cd28e615541d162e66
|
|
BLAKE2b-256 checksum How to use checksums |
d5f8cc2872b3b4145ebbfc253bc46ccc84b4a76231a30bc85dabd5eb0dbadcb0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|