Metadata-Version: 2.4
Name: tai-daf-sdk
Version: 0.2.0
Summary: Python SDK for DAF (Declarative Agentic Framework)
Author-email: Transient AI <dev@transient.ai>
License: MIT
Project-URL: Homepage, https://github.com/transientai/tai-daf-sdk
Project-URL: Repository, https://github.com/transientai/tai-daf-sdk
Project-URL: Issues, https://github.com/transientai/tai-daf-sdk/issues
Project-URL: Changelog, https://github.com/transientai/tai-daf-sdk/blob/main/CHANGELOG.md
Keywords: ai,agents,llm,framework,sdk
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.24.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: python-dotenv>=1.0.0
Provides-Extra: test
Requires-Dist: pytest>=7.0.0; extra == "test"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
Requires-Dist: pytest-cov>=4.0.0; extra == "test"
Provides-Extra: lint
Requires-Dist: black==26.3.1; extra == "lint"
Requires-Dist: ruff>=0.1.0; extra == "lint"
Requires-Dist: mypy>=1.0.0; extra == "lint"
Requires-Dist: types-requests>=2.32.0; extra == "lint"
Requires-Dist: bandit[toml]>=1.8.0; extra == "lint"
Requires-Dist: pip-audit>=2.7.0; extra == "lint"
Requires-Dist: pre-commit>=3.7.0; extra == "lint"
Provides-Extra: dev
Requires-Dist: tai-daf-sdk[lint,test]; extra == "dev"

# DAF SDK

Python SDK for **DAF (Declarative Agentic Framework)** — a platform for building, managing, and orchestrating AI agents and multi-agent teams.

DAF SDK provides a typed, intuitive interface for the entire DAF API: creating agents, running conversations, building teams, managing memory, tools, triggers, and more.

## Features

- **Full API coverage** — Agents, Teams, Sessions, Memory, Tools, Triggers, MCP, A2A, Analytics, Export/Import
- **Sync & Async** — `DAF` for synchronous code, `AsyncDAF` for async/await
- **Streaming** — Real-time token-by-token responses
- **Type hints** — Full typing with Pydantic models for IDE autocompletion
- **Custom tools** — `@custom_tool` decorator to create tools from Python functions
- **Error handling** — Typed exceptions (`APIError`, `NotFoundError`, `ValidationError`, etc.)
- **Context manager** — Automatic resource cleanup with `with` / `async with`

## Requirements

- Python 3.9+
- Running DAF server instance

## Installation

```bash
pip install tai-daf-sdk
```

Or install from source:

```bash
git clone https://github.com/your-org/tai-daf-sdk.git
cd tai-daf-sdk
pip install -e ".[dev]"
```

## Quick Start

```python
from tai_daf_sdk import DAF

client = DAF(
    base_url="http://localhost:8012",
    api_key="daf_your_api_key"
)

# Create an agent
agent = client.agents.create(
    name="assistant",
    system_instructions="You are a helpful assistant.",
    model_provider="Azure",
    model_name="gpt-4o",
    api_key="your-llm-key",
    azure_endpoint="https://your-resource.openai.azure.com",
    azure_deployment="gpt-4o"
)

# Send a message
response = client.agents.messages.send(
    agent_id=agent.id,
    message="What can you help me with?"
)
print(response.response)

# Clean up
client.agents.delete(agent.id)
client.close()
```

### Using Saved LLM Endpoints

Save LLM configurations once and reuse them across multiple agents:

```python
# Save an LLM endpoint configuration
endpoint = client.llm_endpoints.create(
    name="Production GPT-4o",
    provider_type="Azure",
    model_name="gpt-4o",
    api_key="your-llm-key",
    azure_endpoint="https://your-resource.openai.azure.com",
    azure_deployment="gpt-4o",
    is_default=True  # Set as default for Azure
)

# Create agents using the saved endpoint
agent1 = client.agents.create(
    name="assistant",
    system_instructions="You are helpful.",
    llm_endpoint_id=endpoint.id  # Reference saved endpoint
)

agent2 = client.agents.create(
    name="researcher",
    system_instructions="You research topics.",
    llm_endpoint_id=endpoint.id  # Same endpoint, different agent
)

# Update the endpoint once, affects all agents
client.llm_endpoints.update(
    endpoint.id,
    model_name="gpt-4o-mini"  # All agents now use mini
)
```

See [LLM Endpoints documentation](docs/llm_endpoints.md) for more details.

## Authentication

```python
# API key (recommended)
client = DAF(base_url="http://localhost:8012", api_key="daf_...")

# JWT token
client = DAF(base_url="http://localhost:8012", token="eyJ...")

# Login with credentials
client = DAF(base_url="http://localhost:8012")
client.auth.login(email="user@example.com", password="secret")
```

## Configuration

Create a `.env` file for your project:

```properties
DAF_BASE_URL=http://localhost:8012
DAF_API_KEY=daf_your_api_key

# LLM credentials (for agent creation)
AZURE_OPENAI_API_KEY=your_azure_key
AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com
AZURE_OPENAI_DEPLOYMENT=gpt-4o
LLM_MODEL=gpt-4o
```

## Core Concepts

### Agents

Agents are the building blocks of DAF. Each agent has a system prompt, LLM configuration, and optional tools.

```python
# Create
agent = client.agents.create(
    name="researcher",
    system_instructions="You are a research assistant.",
    model_provider="Azure",
    model_name="gpt-4o",
    api_key=os.getenv("AZURE_OPENAI_API_KEY"),
    azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
    azure_deployment=os.getenv("AZURE_OPENAI_DEPLOYMENT"),
    temperature="0.7",
    max_tokens=4096,
    tools=["get_weather", "search_web"]
)

# List
agents = client.agents.list()

# Get
agent = client.agents.get(agent_id)

# Update
client.agents.update(agent_id, temperature="0.3")

# Delete
client.agents.delete(agent_id)

# Send message
response = client.agents.messages.send(agent_id=agent.id, message="Hello")
```

### Streaming

```python
for chunk in client.agents.messages.stream(
    agent_id=agent.id,
    message="Explain quantum computing"
):
    if chunk.get("type") == "text":
        print(chunk["content"], end="", flush=True)
```

### Teams

Teams orchestrate multiple agents working together with defined handoff patterns.

```python
team = client.teams.create(
    name="research_team",
    handoff_pattern="sequential",
    nodes=[
        {"type": "agent", "agent_id": researcher.id, "label": "Researcher"},
        {"type": "agent", "agent_id": writer.id, "label": "Writer"}
    ],
    connections=[
        {"from_node_id": "node_0", "to_node_id": "node_1"}
    ]
)

result = client.teams.execute(team_id=team.id, message="Write about AI trends")
```

### Memory

```python
# Agent memory
client.agents.memory.create(agent_id=agent.id, label="user_name", value="Alice")
memories = client.agents.memory.list(agent_id)

# Shared memory (across agents)
client.memory.shared.create(label="project_context", value="Q4 planning")
```

### Custom Tools

```python
from tai_daf_sdk import custom_tool

@custom_tool
def calculate_bmi(weight_kg: float, height_m: float) -> str:
    """Calculate Body Mass Index from weight and height."""
    bmi = weight_kg / (height_m ** 2)
    return f"BMI: {bmi:.1f}"

client.tools.register(calculate_bmi)
```

### Triggers

```python
# Webhook trigger
trigger = client.triggers.create(
    name="on_new_ticket",
    target_type="agent",
    target_id=agent.id,
    trigger_type="webhook",
    input_template="New ticket: {data.title}"
)

# Schedule trigger
trigger = client.triggers.create(
    name="daily_report",
    target_type="team",
    target_id=team.id,
    trigger_type="schedule",
    trigger_config={"cron": "0 9 * * *", "timezone": "UTC"},
    default_input="Generate the daily report"
)
```

### Export / Import

```python
import json

# Export agent
export_data = client.agents.export(agent_id)
with open("agent_backup.json", "w") as f:
    json.dump(export_data, f, indent=2)

# Import agent
with open("agent_backup.json") as f:
    config = json.load(f)
config["api_key"] = "your-key"
config["azure_endpoint"] = "https://..."
config["azure_deployment"] = "gpt-4o"
result = client.agents.import_agent(config)
```

## Async Support

All resources are available in async mode with `AsyncDAF`:

```python
import asyncio
from tai_daf_sdk import AsyncDAF

async def main():
    async with AsyncDAF(base_url="http://localhost:8012", api_key="daf_...") as client:
        agents = await client.agents.list()

        response = await client.agents.messages.send(
            agent_id=agents[0].id,
            message="Hello!"
        )
        print(response.response)

asyncio.run(main())
```

## Available Resources

| Resource | Description |
|----------|-------------|
| `client.agents` | Create, manage, execute AI agents |
| `client.agents.messages` | Send messages, stream responses |
| `client.agents.memory` | Agent-specific memory (create, list, get, update, delete) |
| `client.llm_endpoints` | Saved LLM endpoint configurations |
| `client.teams` | Multi-agent workflows and orchestration |
| `client.sessions` | Conversation history management |
| `client.memory.shared` | Shared memory across agents |
| `client.tools` | Built-in and custom tools |
| `client.triggers` | Webhooks, schedules, event triggers |
| `client.analytics` | Usage statistics and metrics |
| `client.mcp` | Model Context Protocol servers |
| `client.a2a` | Agent-to-Agent protocol |
| `client.auth` | Authentication (login, API keys) |

## Error Handling

```python
from tai_daf_sdk import DAF, APIError, NotFoundError, ValidationError

client = DAF(base_url="...", api_key="...")

try:
    agent = client.agents.get("nonexistent")
except NotFoundError:
    print("Agent not found")
except ValidationError as e:
    print(f"Invalid request: {e}")
except APIError as e:
    print(f"API error {e.status_code}: {e.message}")
```

All exception types:

| Exception | When |
|-----------|------|
| `DAFError` | Base exception for all SDK errors |
| `APIError` | General API error with status code |
| `AuthenticationError` | Invalid or missing credentials |
| `NotFoundError` | Resource not found (404) |
| `ValidationError` | Invalid request data (422) |
| `RateLimitError` | Too many requests (429) |
| `InternalServerError` | Server error (500) |
| `ConnectionError` | Cannot reach the server |
| `TimeoutError` | Request timed out |

## CI & Code Quality

### Pre-commit Hooks

Run once after cloning: `pre-commit install`

| Hook | Tool | What it catches |
|------|------|-----------------|
| Format | black | Auto-formats Python before commit — fails if changes are made |
| Lint | ruff | Style, unused imports, security patterns, bugbear rules |
| Type check | mypy | Type errors in staged Python files |
| Secrets scan | Gitleaks | API keys, tokens, credentials in staged files |

### CI Checks (push + PR on `main`)

**Code Quality**

| Check | Tool | What it catches |
|-------|------|-----------------|
| Format check | black | Code not formatted consistently — spacing, line breaks, quotes |
| Lint | ruff | Bad patterns, unused imports, code style violations |
| Type check | mypy | Type mismatches, wrong return types, missing attributes |
| Install consistency | pip install -e `.[lint]` | Dependency resolution failures before lint/test |

**Security Scan**

| Check | Tool | What it catches |
|-------|------|-----------------|
| SAST | Bandit | Hardcoded passwords, SQL injection patterns, use of unsafe functions |
| Dependency audit | pip-audit | Known CVEs in dependencies |
| Secrets scan | Gitleaks | API keys, tokens, credentials accidentally committed |

## Development

```bash
# Install with dev dependencies
pip install -r requirements-dev.txt

# Install pre-commit hooks (run once after cloning)
pre-commit install

# Run tests
pytest

# Run specific test
pytest tests/test_agents.py -v

# Format code
black tai_daf_sdk tests
ruff check tai_daf_sdk tests

# Type checking
mypy tai_daf_sdk
```

## Documentation

Detailed guides for each feature:

**Agents**
- [Agents — CRUD & Execution](docs/agents.md)
- [Agent Tools](docs/agent_tools.md)
- [Agent Key Parameters](docs/agent_key_params.md)
- [Agent Templates](docs/agent_templates.md)
- [Agent Persona](docs/agent_persona.md)
- [Custom Tools](docs/custom_tools.md)

**LLM Configuration**
- [LLM Endpoints](docs/llm_endpoints.md)

**Execution**
- [Stateful & Stateless Sessions](docs/stateful_stateless.md)
- [Streaming](docs/streaming.md)
- [Async Mode](docs/async_mode.md)
- [Human Approval (Tool-level)](docs/human_approval.md)

**Memory**
- [Memory Operations](docs/memory_operations.md)
- [Memory & Sessions](docs/memory_session.md)
- [Persistent Memory](docs/persistent_memory.md)
- [Prebuilt Tools & Memory](docs/prebuilt_tools_memory.md)
- [Shared Memory (Inter-Agent)](docs/shared_memory_inter_agent.md)

**Teams**
- [Teams — Multi-Agent Orchestration](docs/teams.md)
- [Team Shared Memory](docs/team_shared_memory.md)
- [Team HIL (Human-in-the-Loop)](docs/team_hil.md)
- [Team Orchestration](docs/team_orchestration.md)
- [Team Orchestration — Custom Patterns](docs/team_orchestration_custom.md)
- [Team A2A Protocol](docs/team_a2a.md)

**Advanced**
- [HIL Approval Workflows](docs/hil_approval.md)
- [HIL Notifications](docs/hil_notifications.md)
- [MCP Support](docs/mcp_support.md)
- [Execution Triggers](docs/execution_triggers.md)
- [Export / Import](docs/export_import.md)

## Examples

The `examples/` directory contains 26 runnable examples:

| # | Example | Topic |
|---|---------|-------|
| 01 | `agents.py` | Agent CRUD and execution |
| 02 | `agent_tools.py` | Using tools with agents |
| 03 | `agent_key_params.py` | Temperature, max_tokens, model config |
| 04 | `stateful_stateless.py` | Session management |
| 05 | `async_mode.py` | AsyncDAF usage |
| 06 | `streaming.py` | Streaming responses |
| 07 | `agent_templates.py` | Predefined agent templates |
| 08 | `human_approval.py` | Tool approval workflows |
| 09 | `prebuilt_tools_memory.py` | Built-in tools with memory |
| 10 | `mcp_support.py` | MCP server integration |
| 11 | `custom_tools.py` | @custom_tool decorator |
| 12 | `teams.py` | Team creation and execution |
| 13 | `team_shared_memory.py` | Shared memory in teams |
| 14 | `team_hil.py` | Human-in-the-loop in teams |
| 15 | `team_a2a.py` | Agent-to-Agent protocol |
| 16 | `team_orchestration.py` | Orchestration patterns |
| 17 | `team_orchestration_custom.py` | Custom orchestration |
| 18 | `memory_session.py` | Memory with sessions |
| 19 | `persistent_memory.py` | Persistent memory |
| 20 | `agent_persona.py` | Agent personality config |
| 21 | `shared_memory_inter_agent.py` | Cross-agent memory sharing |
| 22 | `memory_operations.py` | Memory CRUD operations |
| 23 | `hil_approval.py` | HIL approval workflows |
| 24 | `hil_notifications.py` | HIL notifications |
| 25 | `execution_triggers.py` | Webhooks, schedules, events |
| 26 | `export_import.py` | Export/import agents and teams |
| 27 | `llm_endpoints.py` | LLM endpoint management |

## Project Structure

```
tai-daf-sdk/
├── tai_daf_sdk/
│   ├── __init__.py          # Package exports
│   ├── client.py            # DAF and AsyncDAF clients
│   ├── _http.py             # HTTP client (httpx-based)
│   ├── _base.py             # Base resource class
│   ├── auth.py              # Authentication
│   ├── models.py            # Pydantic models
│   ├── exceptions.py        # Exception types
│   ├── decorators.py        # @custom_tool decorator
│   └── resources/
│       ├── agents.py        # Agents + Messages + AgentMemory
│       ├── teams.py         # Teams + Execution
│       ├── sessions.py      # Chat sessions
│       ├── memory.py        # Shared memory
│       ├── tools.py         # Tools management
│       ├── triggers.py      # Execution triggers
│       ├── analytics.py     # Analytics & metrics
│       ├── mcp.py           # MCP servers
│       ├── a2a.py           # Agent-to-Agent
│       └── llm_endpoints.py # LLM endpoint configs
├── docs/                    # Documentation (27 guides)
├── examples/                # Examples (27 scripts)
├── tests/                   # Tests (27 test files)
├── templates/               # Agent templates (JSON)
├── pyproject.toml
└── README.md
```

## License

Copyright © 2026 Transient.AI. All rights reserved.

Internal use only unless explicitly authorized.
