Skip to content

DCAF - DuploCloud Agent Framework

DCAF (DuploCloud Agent Framework) is a Python framework for building LLM-powered AI agents with tool calling and human-in-the-loop approval.


Quick Start

from dcaf.core import Agent, serve
from dcaf.tools import tool

# 1. Define tools
@tool(description="List Kubernetes pods")
def list_pods(namespace: str = "default") -> str:
    return kubectl(f"get pods -n {namespace}")

@tool(requires_approval=True, description="Delete a pod")
def delete_pod(name: str, namespace: str = "default") -> str:
    return kubectl(f"delete pod {name} -n {namespace}")

# 2. Create an agent
agent = Agent(tools=[list_pods, delete_pod])

# 3. Serve it
serve(agent)  # Running at http://0.0.0.0:8000

Test it:

curl -X POST http://localhost:8000/api/chat \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"role": "user", "content": "What pods are running?"}]}'

Key Features

Feature Description
πŸ› οΈ Tool Calling Easy decorator-based tool definitions with auto-generated, dict, or Pydantic schemas
βœ… Human-in-the-Loop Built-in approval flow for dangerous operations
πŸ”Œ Interceptors Hook into request/response for validation, context, security
πŸ”„ Framework Adapters Swap LLM frameworks (Agno, Strands, LangChain) with one parameter
πŸ”— HelpDesk Protocol Full compatibility with DuploCloud HelpDesk messaging
🌐 REST API One-line server with serve(agent)
πŸ“‘ Streaming Real-time token-by-token responses
πŸ”€ Custom Logic Build agents with any structure you need
πŸ”§ MCP Integration Connect to external MCP servers and use their tools

Architecture

How It Works

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Your Code                                β”‚
β”‚                                                                  β”‚
β”‚   agent = Agent(tools=[...])    OR    def my_agent(messages, ctx)β”‚
β”‚   serve(agent)                        serve(my_agent)            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
                             β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        DCAF Core                                 β”‚
β”‚                                                                  β”‚
β”‚   1. Receives HTTP request from HelpDesk                        β”‚
β”‚   2. Converts to simple message format                          β”‚
β”‚   3. Runs your agent logic                                      β”‚
β”‚   4. Handles tool approvals automatically                       β”‚
β”‚   5. Returns response in HelpDesk protocol                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
                             β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    LLM (AWS Bedrock)                             β”‚
β”‚                                                                  β”‚
β”‚   Claude 3.5 Sonnet / Claude 4 / etc.                           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Request/Response Flow

  DuploCloud HelpDesk                      Your Agent
         β”‚                                      β”‚
         β”‚  POST /api/chat                      β”‚
         β”‚  {"messages": [...]}                 β”‚
         β”‚ ───────────────────────────────────► β”‚
         β”‚                                      β”‚
         β”‚                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”
         β”‚                              β”‚ Agent.run()   β”‚
         β”‚                              β”‚ calls LLM     β”‚
         β”‚                              β”‚ with tools    β”‚
         β”‚                              β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                                      β”‚
         β”‚  Tool needs approval?                β”‚
         β”‚  ◄─────────────────────────────────  β”‚
         β”‚  {"tool_calls": [...]}               β”‚
         β”‚                                      β”‚
    β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”                                 β”‚
    β”‚  User   β”‚                                 β”‚
    β”‚ Approvesβ”‚                                 β”‚
    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜                                 β”‚
         β”‚                                      β”‚
         β”‚  POST /api/chat                      β”‚
         β”‚  {tool_calls: [execute: true]}       β”‚
         β”‚ ───────────────────────────────────► β”‚
         β”‚                                      β”‚
         β”‚                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”
         β”‚                              β”‚ Execute tool  β”‚
         β”‚                              β”‚ Return result β”‚
         β”‚                              β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                                      β”‚
         β”‚  {"content": "Done!", ...}           β”‚
         β”‚  ◄─────────────────────────────────  β”‚

Component Overview

Component What It Does
Agent Your LLM-powered assistant with tools
Tools Functions the agent can call (with optional approval)
serve() Runs your agent as a REST API
HelpDesk Protocol Message format for DuploCloud integration

For internal architecture details, see Engineering Handoff.


Two Ways to Build Agents

Option 1: Simple (Agent Class)

For most use cases:

from dcaf.core import Agent, serve

agent = Agent(
    tools=[list_pods, delete_pod],
    system="You are a Kubernetes assistant.",
)
serve(agent)

Option 2: Custom Function

For complex logic (multiple LLM calls, branching, etc.):

from dcaf.core import Agent, AgentResult, serve

def my_agent(messages: list, context: dict) -> AgentResult:
    # Classify intent
    classifier = Agent(system="Classify as: query or action")
    intent = classifier.run(messages)

    if "action" in intent.text:
        # Use tools for actions
        executor = Agent(tools=[...])
        result = executor.run(messages)
        return AgentResult(text=result.text, ...)

    return AgentResult(text=intent.text)

serve(my_agent)

See Custom Agents Guide for patterns.


Endpoints

Endpoint Method Description
/health GET Health check
/api/chat POST Synchronous chat
/api/chat-stream POST Streaming (NDJSON)

Tool Approval

Tools that modify state should require approval:

@tool(requires_approval=True, description="Delete a pod")
def delete_pod(name: str) -> str:
    return kubectl(f"delete pod {name}")

The agent will pause and ask for approval before executing.


Documentation

Getting Started

Core Framework

Reference

Architecture

Legacy (v1)

The original API is still available for existing integrations:


Installation

# From GitHub
pip install git+https://github.com/duplocloud/service-desk-agents.git

# For development
git clone https://github.com/duplocloud/service-desk-agents.git
cd service-desk-agents
pip install -r requirements.txt

Requirements

  • Python 3.12+
  • AWS credentials with Bedrock access
  • Dependencies: fastapi, pydantic, uvicorn, boto3

License

MIT License - See LICENSE for details.


Support