Skip to main content

fred-sdk

fred-sdk is the authoring library for Fred agents.
It provides everything needed to define agents, tools, workflows, and multi-agent compositions — with no dependency on any running platform service.


Where fred-sdk fits

fred-core          Pure utilities — model factories, embeddings, logging
     │
fred-sdk           Execution engine + authoring surface  ← this package
     │              ReAct, Graph, Team, Deep agent types
     │              Tool authoring, HITL, MCP references
     │
fred-runtime       Platform adapters + pod factory
                    SQL checkpointer, LLM routing, FastAPI app factory

Agent logic belongs in fred-sdk.
Infrastructure wiring (DB, MCP server, Keycloak, object store) belongs in fred-runtime.
fred-sdk must stay importable on a bare laptop with no services running.


Installation

pip install fred-sdk[agents]          # agent authoring
pip install fred-sdk[knowledge-base]  # a Knowledge Base pod

The base install carries only configuration, identity and the plain contract models, so a Knowledge Base pod never pulls in the agents platform; [agents] adds fred-core, langchain and langgraph on top.

Requires Python 3.12.


Agent types

ReAct agent

Tool-calling assistant backed by a ReAct loop. The most common agent type.

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:
        # call external API here
        return ToolOutput.text(f"It is sunny in {city}.")

Graph agent

Deterministic workflow with typed state. Nodes are Python functions; edges and conditional routes are declared in GraphWorkflow.

from fred_sdk import GraphAgent, GraphWorkflow, typed_node, StepResult
from pydantic import BaseModel

class MyState(BaseModel):
    message: str = ""
    result: str = ""

@typed_node(MyState)
async def process(state: MyState, ctx) -> StepResult:
    return StepResult(state_update={"result": f"processed: {state.message}"})

class MyGraphAgent(GraphAgent):
    agent_id = "my.graph.agent"
    role = "Processing pipeline"
    description = "Runs a deterministic processing workflow."
    state_schema = MyState
    workflow = GraphWorkflow(
        entry="process",
        nodes={"process": process},
    )

Graph workflow primitives available from fred_sdk:

Primitive What it does
typed_node Decorator — turns a function into a typed graph node
GraphWorkflow Declares nodes, edges, and conditional routes
choice_step Built-in node for HITL choice gates
finalize_step Built-in node that sets final_text and ends the graph
intent_router_step Built-in LLM-powered intent classifier node
model_text_step Built-in node that calls the LLM and stores the result
structured_model_step Built-in node that calls the LLM and parses structured output
StepResult Return type for typed nodes

Team agent

Multi-agent composition. A coordinator routes or sequences work across members.

from fred_sdk import TeamAgent, AgentSpec

class SupportRouter(TeamAgent):
    agent_id = "my.support.router"
    role = "Support request router"
    description = "Routes support requests to the right specialist."
    mode = "route"
    coordinator_instructions = "Pick the right specialist based on user intent."
    members = (
        AgentSpec(name="Billing", role="Billing questions", agent_ref="my.billing.agent"),
        AgentSpec(name="Technical", role="Technical issues", agent_ref="my.technical.agent"),
    )

Three modes:

Mode Behaviour
sequential Members run in order; each is an inline LLM call
dynamic A coordinator LLM decides who runs next after each member
route A coordinator LLM picks exactly one registered agent and delegates the full request

Child agents used as agent_ref targets should set public = False so they are not exposed as top-level models in Open WebUI or other OpenAI-compatible frontends.


Deep agent

Extended ReAct variant with a built-in planning step. Inherits the full ReAct authoring surface; the planning engine is wired by the runtime.

from fred_sdk import DeepAgentDefinition

class MyDeepAgent(DeepAgentDefinition):
    agent_id = "my.deep.agent"
    role = "Deep research assistant"
    description = "Plans and executes multi-step research tasks."
    ...

Tool authoring

Tools are async methods decorated with @tool on a ReActAgent subclass.

from fred_sdk import tool, ToolContext, ToolOutput, ToolInvocationError

@tool("Search internal documents for a query")
async def search_docs(self, query: str, ctx: ToolContext) -> ToolOutput:
    token = ctx.access_token          # bearer token from the request
    user_id = ctx.user_id             # current user
    results = await my_search_api(query, token=token)
    if not results:
        raise ToolInvocationError("No documents found.")
    return ToolOutput.text("\n".join(results))

ToolContext gives the tool access to the runtime context: user_id, team_id, session_id, language, access_token, and invoke_agent() for sub-agent calls.


Human-in-the-loop (HITL)

Pause a graph at a node and wait for user input. Use choice_step for menu-driven flows or emit HumanInputRequest directly for free-text prompts.

from fred_sdk import choice_step, HumanChoiceOption

approve_step = choice_step(
    title="Confirm transfer",
    question="Do you want to proceed with this bank transfer?",
    choices=[
        HumanChoiceOption(id="confirm", label="Yes, confirm"),
        HumanChoiceOption(id="cancel",  label="No, cancel"),
    ],
    routes={"confirm": "execute", "cancel": "abort"},
)

MCP server references

Declare which MCP servers an agent needs. The runtime wires the actual connection.

from fred_sdk import MCPServerRef, MCP_SERVER_KNOWLEDGE_FLOW_CORPUS

class MyRagAgent(ReActAgent):
    agent_id = "my.rag.agent"
    ...
    default_mcp_servers = (MCP_SERVER_KNOWLEDGE_FLOW_CORPUS,)

Built-in MCP server constants:

Constant Connects to
MCP_SERVER_KNOWLEDGE_FLOW_CORPUS Document search and retrieval
MCP_SERVER_KNOWLEDGE_FLOW_FS Workspace file system
MCP_SERVER_KNOWLEDGE_FLOW_TABULAR Tabular data / CSV
MCP_SERVER_KNOWLEDGE_FLOW_OPENSEARCH_OPS OpenSearch operations

Built-in tool references

Pre-built platform tools declared by reference (no implementation needed in the agent):

from fred_sdk import TOOL_REF_KNOWLEDGE_SEARCH, TOOL_REF_ARTIFACTS_PUBLISH_TEXT

class MyAgent(ReActAgent):
    declared_tool_refs = (TOOL_REF_KNOWLEDGE_SEARCH, TOOL_REF_ARTIFACTS_PUBLISH_TEXT)
Constant What it does
TOOL_REF_KNOWLEDGE_SEARCH Semantic/hybrid search over indexed documents
TOOL_REF_RESOURCES_FETCH_TEXT Fetch document content as text
TOOL_REF_ARTIFACTS_PUBLISH_TEXT Publish a text artifact to the workspace
TOOL_REF_GEO_RENDER_POINTS Render geographic points on a map
TOOL_REF_TRACES_SUMMARIZE_CONVERSATION Summarize conversation traces

Testing your nodes offline

Graph nodes reach the model and sub-agents through two calls: context.invoke_agent(...) and context.invoke_structured_model(...) (used by structured_model_step). fred_sdk.testing ships FakeGraphNodeContext, a double covering exactly those two, so a node's business logic can be tested without a real model or a real sub-agent.

from typing import cast
from fred_sdk import AgentInvocationResult, GraphNodeContext
from fred_sdk.testing import FakeGraphNodeContext

context = FakeGraphNodeContext(
    agent_result=AgentInvocationResult(
        agent_id="my.specialist.agent", structured={"trust": "high"}
    ),
    structured_results={"intent": "question_cloud_general"},
)
result = await my_node(state, cast(GraphNodeContext, context))

assert context.agent_calls[0]["agent_id"] == "my.specialist.agent"

A call you did not configure raises AssertionError immediately, so an under-specified test fails loudly instead of silently returning None into your node's logic.


Running an agent

fred-sdk defines agents; fred-runtime executes them. A minimal pod:

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

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

See fred-runtime on PyPI for the full pod setup guide, and fred-samples for a working reference pod.


Knowledge Bases — beta

fred_sdk.knowledge_base tells Fred where a team's documents come from and how to keep them current: declare an identity and configuration fields, write one async handler, call knowledge_base_main(kb). Fred supplies the destination library, a workload identity and a cadence; the handler owns discovery, replay-safe writes and explicit retractions — Fred never infers a deletion from absence. DocumentPublisher is the shortcut for writing: a write is accepted at once and ingested by Fred afterwards, wait follows it to its end, and documents() reads back what the library holds so a run can reconcile against it. Install fred-sdk[knowledge-base]. Working declarations live in the fred-samples repository under knowledge-bases/.

A Knowledge Base acts as a workload, so it needs a deployment that authenticates and a confidential client of its own. A pod started without its client secret and realm fails immediately, naming what it lacks. A stack running with authentication off cannot host one — including for local development.

This surface is beta: pin your fred-sdk version, as it may change between beta releases. Known limits today:

  • Configuration fields are fixed once instances exist — there is no schema migration. Deleting a synchronized folder deletes its documents.
  • A run's fate is visible in the workflow engine only. Counters, summaries and issues a handler returns are not stored or displayed, and Fred offers no run history, manual trigger or worker-health check yet.
  • A relative path is the document key, so a rename reads as a delete plus an add.
  • Cadences are hourly, daily or weekly, with no immediate first run.

The label applies to Knowledge Bases only, not to this SDK's agent APIs.


Package PyPI Role
fred-core pypi Pure utilities — logging, model factories, embeddings, portable observability
fred-sdk pypi This package
fred-runtime pypi Platform adapters + pod factory

License

Apache License 2.0.

Metadata

Release files for fred-sdk 4.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fred-sdk 4.1.0
File Size Uploaded
fred_sdk-4.1.0.tar.gz 204.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fred-sdk 4.1.0
File Interpreter ABI Platform
fred_sdk-4.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 398.2 kB

Release files / fred_sdk-4.1.0.tar.gz

Download URL fred_sdk-4.1.0.tar.gz
Size 204.0 kB
Tags Source
SHA-256 checksum
How to use checksums
ed7070d64f69289713dd1f3b1057d789a64b39422b99afcd51712cd893ec8318
BLAKE2b-256 checksum
How to use checksums
e794ba414889867b1fc2076129cd1c575a201d9983481cd3788463dcbb332f88
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / fred_sdk-4.1.0-py3-none-any.whl

Download URL fred_sdk-4.1.0-py3-none-any.whl
Size 194.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
23d5b53100ebe2c02d9e5f0d4538df69bf99411980c1ae8edfa599fc8d6bed6b
BLAKE2b-256 checksum
How to use checksums
b439e8b26c502e9ea3cf4f292dd1d572160c916f909bc0a2637b5aa3d645868b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

4.5.1

2 release files

4.5.0

2 release files

4.4.3

2 release files

4.4.2

2 release files

4.4.1

2 release files

4.4.0

2 release files

4.3.0

2 release files

This release

4.1.0 This release

2 release files

4.0.0

2 release files

3.7.0

2 release files

3.5.0

2 release files

3.4.3

2 release files

3.4.2

2 release files

3.4.1

2 release files

3.4.0

2 release files

3.3.5

2 release files

3.3.4

2 release files

3.3.3

2 release files

3.3.2

2 release files

3.3.1

2 release files

3.3.0

2 release files

3.1.1

2 release files

3.1.0

2 release files

2.0.9

2 release files

2.0.8

2 release files

2.0.7

2 release files

2.0.6

2 release files

2.0.5

2 release files

2.0.3

2 release files

2.0.2

2 release files

2.0.1

2 release files

2.0.0

2 release files

0.1.11

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page