Skip to main content

Agents & Sub-Agents

An agent is an autonomous AI entity with its own system prompt, tool set, knowledge bases, and LLM configuration. Agents can be composed into hierarchies where an orchestrator delegates to specialized sub-agents.

Agent types

System agents

System agents are the built-in specialists that ship with AgentFlow:
AgentDomainCapabilities
MainAgentOrchestrationRoutes requests to the right sub-agent; never handles domain actions directly
EmailsAgentEmailRead, search, draft, send, reply via connected email accounts
TasksAgentTasksCreate, assign, track, prioritize tasks and follow-ups
MeetingsAgentCalendarSchedule, check availability, analyze transcripts
ResearchAgentResearchWeb search, company news, SEC filings, industry intelligence
RecordsAgentCRMQuery and manage accounts, contacts, opportunities, pipelines
SnowflakeAgentDataSnowflake query and analysis workflows
JediAgentInternalHidden sub-agent used by the jedi_council tool; not exposed to MainAgent
There is no built-in GeneralSubAgent. Unknown domains should be handled by the orchestrator as missing capability rather than routed to a catch-all.

Dynamic sub-agents

You can create custom sub-agents at runtime under an existing parent agent. Dynamic sub-agents are full agents that can have their own tools, knowledge bases, model configuration, and prompt:
from agentflow import AsyncAgentFlow

async with AsyncAgentFlow.from_profile("prod") as client:
    parent_id = (await client.agents.by_name("MainAgent")).id

    support_agent = await client.agents.subagents.create(
        parent_id,
        name="SupportAgent",
        description="Escalated support specialist",
        system_prompt="You are a customer support specialist.",
        enable_planning=True,
        llm_config={"model": "openai/gpt-5.4-mini", "temperature": 1.0, "max_tokens": 4000},
        knowledge_bases=["550e8400-e29b-41d4-a716-446655440000"],
        tool_assignments=["lookup_ticket"],
    )
Dynamic sub-agent knowledge_bases are KB IDs. tool_assignments on create/update are tool names stored with the sub-agent; the dedicated tool assignment endpoint accepts tool UUIDs.

Configuration

Agents are configured in the backend, seeded into the tenant database, and managed through /api/v1/agent/* endpoints. The Python SDK mirrors that resource shape:
from agentflow import AsyncAgentFlow

async with AsyncAgentFlow.from_profile("prod") as client:
    agents = await client.agents.list()
    analytics = next(agent for agent in agents if agent.name == "AnalyticsAgent")

    await client.agents.update(
        analytics.id,
        system_prompt="You analyze data and produce concise, actionable insights.",
        enable_planning=True,
        enable_reflection=True,
        llm_config={"model": "openai/gpt-5.4-mini", "temperature": 1.0, "max_tokens": 4000},
    )

Capabilities

CapabilityConfig field or surfaceWhat it does
Planningenable_planningAgent decomposes complex requests into multi-step plans before execution
Retrievalknowledge_bases request field, direct capability endpoint, or registered retrieval toolsSearch assigned knowledge bases for relevant context
Reflectionenable_reflectionAgent evaluates its own response quality and can iterate
Retrieval is available in three surfaces:
  • Request-scoped retrieval: when knowledge_bases are passed on a chat request, assigned matching KBs are searched before the model call and injected as context.
  • Direct capability endpoint: POST /api/v1/agent/{agent_id}/capability/retrieve invokes retrieval directly.
  • Model-callable retrieval tool: retrieval is available to the model only when a retrieval tool is registered or assigned through the normal tool system.
Related capability routes:
POST /api/v1/agent/{agent_id}/capability/retrieve
POST /api/v1/agent/{agent_id}/capability/plan
POST /api/v1/agent/{agent_id}/capability/reflect

Agent lifecycle

Via SDK

from agentflow import AgentFlow

with AgentFlow.from_profile("prod") as client:
    agents = client.agents.list()
    agent_id = {agent.name: agent.id for agent in agents}["MainAgent"]

    agent = client.agents.retrieve(agent_id)
    config = client.agents.get_config(agent_id)

    updated = client.agents.update(
        agent_id,
        llm_config={"model": "openai/gpt-5.4-mini", "temperature": 1.0},
    )

Via REST API

# List agents
GET /api/v1/agents

# Get agent details
GET /api/v1/agent/{agent_id}

# Get or update agent config
GET /api/v1/agent/{agent_id}/config
PATCH /api/v1/agent/{agent_id}/config

# Delete an agent
DELETE /api/v1/agent/{agent_id}

# Create a sub-agent under a parent
POST /api/v1/agent/{parent_id}/subagents

Tool and knowledge base composition

Agents are composable building blocks. Tools and knowledge bases are assigned through agent-scoped resources:
from agentflow import AsyncAgentFlow

async with AsyncAgentFlow.from_profile("prod") as client:
    agent_id = (await client.agents.by_name("MainAgent")).id

    tools = await client.agents.tools.list(agent_id)
    kbs = await client.agents.knowledge_bases.list(agent_id)

    response = await client.agents.knowledge_bases.search(
        agent_id,
        kbs[0].id,
        query="How does pricing work?",
        limit=5,
    )

    for document in response.documents:
        print(document.content[:200])

Chat request parameters

The POST /api/v1/agent/{agent_id}/chat endpoint accepts a rich set of parameters for controlling execution. Every parameter beyond message, conversation_id, and message_id is optional.

Core

ParameterTypeDescription
messagestringUser message (required)
conversation_idstringConversation ID for multi-turn context (required)
message_idstringStable unique identifier for this user message (required)
streambooleanStream response via SSE (default: true)
verbosebooleanInclude detailed execution events in the stream (default: false)
Generate conversation_id once per conversation and message_id once per submitted user message. Reuse the same message_id when retrying the same user action after a timeout, reconnect, or duplicate-submit response.

LLM overrides

ParameterTypeDescription
modelstringOverride the model for this run, e.g. "openai/gpt-5.4-mini"
temperaturefloatOverride temperature
max_tokensintegerOverride max output tokens
top_pfloatOverride nucleus sampling (0.0-1.0)
frequency_penaltyfloatOverride frequency penalty
presence_penaltyfloatOverride presence penalty
max_turnsintegerMaximum agent turns (tool calls + responses)

Reasoning

ParameterTypeDescription
reasoning_effortstringReasoning depth. Supported values are model-specific; OpenAI GPT-5.4 models accept "none", "low", "medium", "high", "xhigh", while some models accept a smaller set.
reasoning_summarystringReasoning output: "auto", "concise", "detailed"

Context & attachments

ParameterTypeDescription
attachment_idsstring[]File IDs from upload (triggers vision model for images)
knowledge_basesstring[]Knowledge base IDs to make available for this request
retrieval_optionsobjectBounded per-run KB search tuning, such as top_k, search_type, metadata_filters, and reranking flags
context_refsobject[]Entity references, e.g. [{"system":"crm","type":"account","id":"001x"}]
skillsstring[]Optional allowlist that narrows the agent’s skill catalog
artifactsstring[]Optional allowlist that narrows the agent’s artifact catalog
image_detailstringVision resolution: "low", "high", "auto" (default)
session_contextobjectClient-side context (current page, selected data, route info)
client_timezonestringIANA timezone for temporal awareness, e.g. "America/New_York"

Capability overrides

ParameterTypeDescription
enable_planningbooleanOverride agent planning for this request
enable_reflectionbooleanOverride agent reflection for this request
selected_toolsstring[]Restrict which tools the agent can use for this request
enable_query_rewritebooleanRewrite KB search queries against prior conversation context

Advanced metadata

These fields are usually set by SDKs, embedded UIs, or orchestration layers rather than typed into a public chat form.
ParameterTypeDescription
call_idstringOptional client correlation ID stored with the run. The server still generates the runtime call_id used for streaming and cancellation.
sourcestringOrigin label such as a UI surface, automation, or integration
source_idstringStable ID from the origin system
source_metadataobjectExtra origin metadata for audit, analytics, or routing
POST /api/v1/agent/{agent_id}/chat
Content-Type: application/json

{
  "message": "Analyze the Acme Corp deal and draft a follow-up email",
  "conversation_id": "conv_001",
  "message_id": "msg_042",
  "stream": true,
  "model": "openai/gpt-5.4-mini",
  "temperature": 1.0,
  "max_tokens": 4000,
  "reasoning_effort": "high",
  "knowledge_bases": ["550e8400-e29b-41d4-a716-446655440000"],
  "context_refs": [
    { "system": "crm", "type": "account", "id": "001ABC123" }
  ],
  "enable_planning": true,
  "client_timezone": "America/New_York"
}

Multi-agent orchestration

When a user sends a message, the orchestrator:
  1. Parses intent - identifies which domain(s) the request touches
  2. Delegates - routes to the appropriate sub-agent(s)
  3. Sequences - for multi-part requests, delegates to each sub-agent in order
  4. Aggregates - combines sub-agent responses into a coherent reply
The entire execution is traced via structured events with call_id hierarchies, so you can observe exactly which agents and tools were invoked for every request.