docs / authoring

Add your agent

Build a custom agent as a standalone agentic pod with fred-sdk and fred-runtime, run it locally, and enroll it with a Fred control plane — deployed on your terms, in your own repository.

Scope & audience

For developers building a custom agent for Fred. You author the agent with a small Python SDK, wrap it in an HTTP server (the "pod"), and a Fred control plane discovers and routes to it. You never fork the platform — an agent is a self-contained deployable unit that the platform enrolls.

Everything below uses the current authoring surface (fred_sdk + fred_runtime). For working, maintained examples, use the sample agents — they are the source of truth for current patterns.

The model — an agent is a pod

Fred separates authoring from execution across three published packages. You depend on the first two:

sdk
fred-sdk — author
The authoring surface: ReAct, Graph, and Team agent primitives, tools, and HITL. Pure Python, no infrastructure — it imports on a bare laptop with nothing running.
runtime
fred-runtime[app] — serve
The pod factory: turns your agent registry into a FastAPI service with execution, SSE streaming, checkpoints, HITL, LLM routing, MCP wiring, and security.
core
fred-core — utilities
Shared low-level utilities (model factories, embeddings, logging). Pulled in transitively; you rarely import it directly.
YOUR REPOSITORY agent — fred-sdk registry.py main.py — create_agent_app deps: fred-sdk · fred-runtime[app] python -m yourpod Agentic pod FastAPI · fred-runtime GET /agents/templates POST /agents/execute · SSE checkpoints · HITL Fred control plane discovers & enrolls templates ManagedAgentInstance per team team-scoped execution Keycloak JWT · OpenFGA ReBAC build & run pull /agents/templates execute (team-scoped)

You build and run the pod from your own repository. The control plane pulls the pod's template catalog to discover its agents, a team enrolls one as a managed instance, and execution is routed back to the pod — authorized per team via Keycloak and OpenFGA.

Author with fred-sdk

Install the SDK (Python 3.12) and write an agent. A ReAct agent is a class with an id, a role, a description, a system prompt, and one or more @tool methods:

pip install "fred-runtime[app]" fred-sdk
from fred_sdk import ReActAgent, tool, ToolContext, ToolOutput

class WeatherAgent(ReActAgent):
    agent_id = "my.weather.agent"
    role = "Weather assistant"
    description = "Answers weather questions using the get_weather tool."
    system_prompt_template = "You are a helpful weather assistant."

    @tool("Get current weather for a city")
    async def get_weather(self, city: str, ctx: ToolContext) -> ToolOutput:
        return ToolOutput.text(f"It is sunny in {city}.")

WEATHER_AGENT = WeatherAgent()

The required fields on any definition are agent_id, role, and description. The ToolContext gives a tool the caller's user_id, team_id, session_id, language, and access token — and invoke_agent() to call another agent. Tools can be local Python (as above), built-in tool refs, or MCP-backed for external systems.

Agent shapes

The SDK offers four authoring shapes — pick the simplest that fits:

ReAct
ReActAgent
Tool-first assistant with a reason-act loop. The default choice for "answer questions, call tools".
Graph
GraphAgent
A deterministic workflow over typed state, with built-in nodes (routing, structured model calls, finalize). For pipelines where the steps are known.
Team
TeamAgent
Multi-agent composition — a coordinator delegating to child agents. Modes: sequential, dynamic, route.
Deep
DeepAgentDefinition
An extended ReAct agent with a planning step wired by the runtime, for longer multi-step tasks.
Human-in-the-loop is first-class: emit HumanInputRequest / HumanChoiceOption from any shape and the runtime pauses, surfaces the prompt to the UI, and resumes on the reply — continuity handled transparently by the checkpointer.

Serve it as a pod

A pod is three tiny files plus config. The runtime does the rest — an HTTP server with execution, streaming, sessions, checkpoints, HITL, and an OpenAI-compatible endpoint.

# registry.py
from myapp.agents import WEATHER_AGENT

REGISTRY = {WEATHER_AGENT.agent_id: WEATHER_AGENT}

# main.py
from fred_runtime.app import create_agent_app, load_agent_pod_config
from myapp.registry import REGISTRY

app = create_agent_app(registry=REGISTRY, config=load_agent_pod_config())

# __main__.py
import uvicorn
uvicorn.run("myapp.main:app", host="0.0.0.0", port=8000)

A configuration.yaml (path via CONFIG_FILE) sets the pod name, base path, host/port, the Knowledge Flow URL, observability, and optional security; a .env (path via ENV_FILE) carries model keys. The router is mounted under your configured base path:

GET
/agents/templates
The executable template catalog — this is the endpoint a control plane reads to discover your agents.
POST
/agents/execute · /agents/execute/stream
Single-turn execution, and an SSE stream of runtime events (thoughts, tool calls, tokens, HITL).
GET
/agents · /agents/mcp-catalog · /v1/chat/completions
List registered agents, the MCP catalog, and an OpenAI-compatible chat endpoint (on by default).

Run & test locally

Start the pod, then drive it with the bundled CLI — no control plane or UI required:

# start the pod (SQLite checkpointer in dev — no database needed)
ENV_FILE=./config/.env CONFIG_FILE=./config/configuration.yaml python -m myapp

# talk to it: an interactive client for any pod
fred-agents-cli --base-url http://127.0.0.1:8000/<base_url> --agent my.weather.agent
In development the runtime uses a local SQLite checkpointer, so multi-turn conversations and HITL work end to end with zero infrastructure. In production the same code path uses PostgreSQL.

Enroll with a control plane

The control plane is the sole authority for discovery, enrollment, and execution authorization. It pulls your pod's catalog from a static list in its configuration — point it at your pod's base URL:

# control-plane configuration.yaml
platform:
  runtime_catalog_sources:
    - runtime_id: my-agents          # stable logical id
      base_url: http://my-agents:8000/<base_url>   # reachable from control-plane
      ingress_prefix: /runtime/my-agents          # browser-facing prefix
      enabled: true

Then the lifecycle is:

  1. The control plane reads GET {base_url}/agents/templates and surfaces your agents as templates.
  2. A team admin enrolls a template, creating a team-owned managed instance (with its own tuning — prompt overrides, model profile, selected MCP servers).
  3. Execution goes to the managed instance and is team-scoped: your pod authorizes each call with the caller's Keycloak JWT and an OpenFGA (ReBAC) check on the team before running.
Today, discovery is a pull from the static catalog — the authoritative production mechanism. Push self-registration and Kubernetes-native auto-discovery are on the roadmap; the static catalog is what a pod needs to expose right now.

Examples to start from

Two working references — copy from these rather than from prose:

samples
fred-samples — ready-to-run pods
A standalone sample repository with a General Assistant, a Bank Transfer HITL flow (two confirmation gates), a Postal Tracking agent (live map + HITL rerouting), and a Team of 3 (a router delegating to a Graph and two ReAct agents), each paired with example MCP servers. Quickstart: set a model key in .env, start the MCP servers, make run the pod, make chat.
default
fred-agents — the default pod
The reference agentic pod shipped with Fred and the concrete implementation of the three-file pattern. It hosts a range of agents (RAG expert, SQL expert, mind-map and comparison graph agents, and more) you can read as templates.

Deploy

A pod is an ordinary container. Build an image whose entrypoint runs your module (python -m myapp) and externalize the config directory. Deploy it as a Kubernetes Service reachable from the control plane, then add its runtime_catalog_sources entry. Because the pod owns its own database checkpointer, it scales independently of the rest of the platform.

For the surrounding cluster — the control plane, Postgres, Keycloak, OpenFGA, OpenSearch, Temporal, and how object storage auth works — see Deploying Fred on GCP / GKE.