Standalone WFO search agent for deployment. Exposes the orchestration search agent via AG-UI, A2A, and MCP protocols.
cp .env.example .env
# Edit .env with your DATABASE_URI and LLM settings
uv sync
uv run uvicorn orchestrator_agent.app:app --port 8080| Path | Protocol | Description |
|---|---|---|
POST /agui |
AG-UI | SSE streaming for frontend |
POST / |
A2A | Agent-to-agent JSON-RPC (message/send, message/stream) |
GET /.well-known/agent.json |
A2A | Agent card discovery |
/mcp |
MCP | Model Context Protocol tools |
GET /health |
REST | Health check |
docker compose up --build# Install demo dependencies
uv sync --group demo
# AG-UI: stream a search query
uv run demos/agui_client.py "find active subscriptions"
# AG-UI: follow-up on the same thread
uv run demos/agui_client.py "export them" <thread-id>
# MCP: run all smoke tests (search, aggregate, ask)
uv run demos/mcp_client.py
# MCP: single tool
uv run demos/mcp_client.py search "active subscriptions"
# A2A: delegate to the agent via CrewAI
uv run demos/a2a_client.py <subscription-uuid>| Variable | Default | Description |
|---|---|---|
DATABASE_URI |
(required) | PostgreSQL connection URI for the WFO database |
ORCHESTRATOR_API_URL |
http://localhost:8080 |
URL of the orchestrator-core API |
BASE_URL |
http://localhost:8080 |
Public URL of this agent service |
AGENT_MODEL |
openai:gpt-4o |
LLM model in provider:model format |
AGENT_API_BASE |
(none) | Custom base URL for the LLM provider (OpenAI-compatible) or Azure endpoint |
AGENT_API_KEY |
(none) | API key for the LLM provider |
AGENT_API_VERSION |
(none) | API version for Azure OpenAI (e.g. 2024-12-01-preview) |
AGENT_DEBUG |
false |
Enable debug logging for agent execution |
OAUTH2_ACTIVE |
false |
Enable authenticated requests to the orchestrator |
OAUTH2_TOKEN_ENDPOINT |
(none) | OAuth2 token endpoint URL (required when OAUTH2_ACTIVE=true) |
OAUTH2_CLIENT_ID |
(none) | OAuth2 client ID (required when OAUTH2_ACTIVE=true) |
OAUTH2_CLIENT_SECRET |
(none) | OAuth2 client secret (required when OAUTH2_ACTIVE=true) |
By default the agent uses the standard OpenAI API with the OPENAI_API_KEY environment variable. To use a custom OpenAI-compatible endpoint, set AGENT_API_BASE and/or AGENT_API_KEY:
# Local Ollama
AGENT_MODEL=openai:llama3
AGENT_API_BASE=http://localhost:11434/v1
# LiteLLM proxy or other OpenAI-compatible endpoint
AGENT_MODEL=openai:gpt-4o
AGENT_API_BASE=https://my-proxy.example.com/v1
AGENT_API_KEY=sk-custom-key
# Azure OpenAI
AGENT_MODEL=azure:gpt-4o
AGENT_API_BASE=https://my-resource.openai.azure.com/
AGENT_API_KEY=azure-api-key
AGENT_API_VERSION=2024-12-01-previewThe azure: prefix on AGENT_MODEL (or setting AGENT_API_VERSION) selects the Azure provider automatically. When none of AGENT_API_BASE, AGENT_API_KEY, or AGENT_API_VERSION is set, AGENT_MODEL is passed directly to pydantic-ai as a model string (existing behavior).
This repo contains only the agent logic (planner, skills, tools, adapters, state, memory, prompts). The search infrastructure (query engine, filters, retrievers, indexing, DB models) lives in orchestrator-core and is imported as a dependency via orchestrator-core[search] (along with everything else for now).
Request ──► AG-UI adapter ──► AgentAdapter.run_stream_events()
──► A2A adapter ──► └─► Planner.execute()
──► MCP adapter ──► └─► SkillRunner.run()
The A2A adapter uses a2a-sdk server primitives (AgentExecutor, DefaultRequestHandler, A2AFastAPIApplication). The SDK handles JSON-RPC routing, SSE streaming, task lifecycle, and agent card serving. The adapter implements a single WFOAgentExecutor.execute() method that drives the pydantic-ai event stream and publishes A2A events via TaskUpdater.
The agent advertises skills (search, aggregation, result actions, text response) on the agent card. Clients can target a specific skill by passing {"skill_id": "<action>"} in the message metadata to bypass the planner.