Appearance
Create Your First Agent
This guide explains how to build and run a single-agent swarm in SwarmForge. It does not cover multi-agent routing or FastAPI deployment.
This guide is for Python developers who already installed SwarmForge and want the shortest path to a working agent. It assumes that you can run Python code and configure a provider-backed model.
After reading this guide, you should be able to:
- define a single
SwarmNode - attach Python tools to that node
- run the agent with
process_swarm_stream(...)
In SwarmForge, a first agent is usually a single-node swarm. You define one SwarmNode, wrap it in a SwarmDefinition, and run it through process_swarm_stream(...) with a session.
This page shows the shortest path in three parts:
- create the agent
- add tools
- run a full example
Before running the full example, copy .env.example to .env, set MODEL_PROVIDER, set LLM_MODEL, and add the matching API key. For the tool example on this page, use a model that supports tool calling.
Quick Start Tabs
python
from swarmforge.swarm import SwarmDefinition, SwarmNode, SwarmSession
swarm = SwarmDefinition(
id="assistant",
name="Assistant Swarm",
nodes=[
SwarmNode(
id="assistant",
node_key="assistant",
name="Assistant",
system_prompt=(
"You are a concise support assistant. "
"Answer directly and ask for one missing detail when needed."
),
is_entry_node=True,
)
],
)
session = SwarmSession(id="session-1", swarm=swarm)python
from swarmforge.swarm import function_tool
async def lookup_order(order_id: str, state=None, context=None):
"""Fetch order status for a customer order.
Args:
order_id: The order identifier.
"""
return {
"order_id": order_id,
"tenant": state["tenant"],
"account_id": context.state.get("account_id"),
"status": "shipped",
}
swarm.nodes[0].enabled_tools = [function_tool(handler=lookup_order)]python
import asyncio
import json
from swarmforge.env import require_env_vars
from swarmforge.evaluation.provider import ModelConfig
from swarmforge.swarm import (
InMemorySessionStore,
SwarmDefinition,
SwarmNode,
SwarmSession,
build_turn_runner,
function_tool,
process_swarm_stream,
)
async def lookup_order(order_id: str, state=None, context=None):
"""Fetch order status for a customer order.
Args:
order_id: The order identifier.
"""
return {
"order_id": order_id,
"tenant": state["tenant"],
"account_id": context.state.get("account_id"),
"status": "shipped",
}
tool_registry = {"lookup_order": lookup_order}
swarm = SwarmDefinition(
id="assistant",
name="Assistant Swarm",
nodes=[
SwarmNode(
id="assistant",
node_key="assistant",
name="Assistant",
system_prompt=(
"You are a concise support assistant. "
"Always call lookup_order before answering an order-status question."
),
enabled_tools=[function_tool(handler=lookup_order)],
is_entry_node=True,
)
],
)
async def main():
require_env_vars("MODEL_PROVIDER", "LLM_MODEL")
session = SwarmSession.from_state(
id="session-1",
swarm=swarm,
state={"account_id": "ACME-991"},
)
store = InMemorySessionStore()
turn_runner = build_turn_runner(ModelConfig())
async for event in process_swarm_stream(
session,
"Where is order 123?",
store=store,
turn_runner=turn_runner,
tool_registry=tool_registry,
tool_state={"tenant": "acme"},
):
print(json.dumps(event, indent=2))
if __name__ == "__main__":
asyncio.run(main())What Each Part Does
Create Agent
SwarmNode is the agent definition. For a first agent, you usually only need:
idnode_keynamesystem_promptis_entry_node=True
Put that node inside a SwarmDefinition, then create a SwarmSession for runtime state. Fields such as intent and capabilities are optional metadata, not required for the basic runtime path.
Pass External State
If your application already knows request-scoped facts, pass them directly into the session:
python
session = SwarmSession.from_state(
id="session-1",
swarm=swarm,
state={"account_id": "ACME-991", "priority": "high"},
)Those values are then available in two places:
- tools through
context.state - dynamic prompts through
SystemPromptContext.state
Add Tools
function_tool(...) plus a plain tool_registry mapping is the simplest way to add Python tools:
- define a sync or async Python function
- let SwarmForge infer the tool schema from the function signature
- attach the tool schema to a node with
function_tool(handler=...) - pass
tool_registry={"tool_name": handler}intoprocess_swarm_stream(...)so the runtime can resolve the callable - pass
tool_state=...when the handler needs shared runtime-only dependencies
Injected runtime-only parameters such as context, state, session, visible_state, and visible_global_variables are available to handlers but are not exposed in the model-visible JSON schema.
Example Usage
The runnable example uses the shared OpenAI-compatible turn runner helper. Set MODEL_PROVIDER, LLM_MODEL, and the matching API key before running it. Exact phrasing varies by model, but the runner still forwards the same runtime inputs:
config.system_instructionconfig.toolsconfig.state- the current turn history in
contents
When To Use This Pattern
Use this page's pattern when you want:
- one assistant with no handoffs yet
- a fast way to test tool execution
- a minimal runtime integration before moving to a larger multi-agent graph
If you need handoffs between multiple agents, continue with Create Your First Multi-Agent Swarm. If you want prompt-generated graph definitions, continue with Authoring.