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.0a4.tar.gz (37.4 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.0a4-py3-none-any.whl (29.8 kB view details)

Uploaded Python 3

File details

Details for the file tai_daf_sdk-2.0.0a4.tar.gz.

File metadata

  • Download URL: tai_daf_sdk-2.0.0a4.tar.gz
  • Upload date:
  • Size: 37.4 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.0a4.tar.gz
Algorithm Hash digest
SHA256 689ac311369850f34e4ffd5e395b631be208f630a42171a5b8a0b25f5654da9d
MD5 95b1a21c5a317adedcd4e198e4089bc5
BLAKE2b-256 2977d5ad4f4bcd50f31c022f5901bc8e03e753f0d1eb67777bf88924a2e3c07a

See more details on using hashes here.

File details

Details for the file tai_daf_sdk-2.0.0a4-py3-none-any.whl.

File metadata

  • Download URL: tai_daf_sdk-2.0.0a4-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.0a4-py3-none-any.whl
Algorithm Hash digest
SHA256 1cd36c8cadfaba0df36e432d0493c13d3145f2366fde77aaaa0eb56e558c9777
MD5 6fda821214d9795868be3a89b8761d1f
BLAKE2b-256 083c3be5fd30f9c89c5d9e57edbf4681dd12d4645b54a68fcedced19c6143324

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