Skip to main content

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 with daf_). Get one from Settings → API keys in the webapp.
  • token (str) — Bearer JWT alternative to API key. Only one of api_key / token at 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 agent
    • 02_swarm_workflow.py — compose a two-agent swarm via workflow drafts
    • 03_triggers.py — webhook + cron + event triggers
    • 04_memory.py — per-agent memory + shared memory
    • 05_guardrails.py — attach a guardrail to an agent
    • 06_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 map
  • types.py — TypedDict per tool input
  • client.pyi — IDE stubs for autocomplete
  • models.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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tai_daf_sdk-2.0.0a3.tar.gz (37.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tai_daf_sdk-2.0.0a3-py3-none-any.whl (29.8 kB view details)

Uploaded Python 3

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

Hashes for tai_daf_sdk-2.0.0a3.tar.gz
Algorithm Hash digest
SHA256 14b5fe6904069eefb9c518019ea6a6bd4611437b1af4c90571fd4dde4ac3fd26
MD5 b24f656667a5030c5ef9d92eb30aa0e4
BLAKE2b-256 da44bf43f0eadbffbfb1c7c6bfaf36586ea6b5068cb8eba28d0caae0baa4b472

See more details on using hashes here.

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

Hashes for tai_daf_sdk-2.0.0a3-py3-none-any.whl
Algorithm Hash digest
SHA256 e24e56e819be4225285a4aa892b3a206f93162b7fbcab2dbc9950a967c14053e
MD5 ba0066d907ec2b7f00523e8ee547bd3a
BLAKE2b-256 ae864c81024a0d85b5b4cac0b7ca9c13ccc739774763dfb153fa8536ce9a1067

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page