Swap providers, not code
Anthropic, OpenAI, Google, and DeepSeek sit behind one config. Change the model with a single line — your agent code never changes.
Provider-agnostic runtimes, persistent memory, hierarchical agent graphs, and Clean Architecture — swap any layer without rewriting your code.
from swarmline import Agent, AgentConfig
agent = Agent(AgentConfig(
system_prompt="You are a helpful assistant.",
runtime="thin",
))
result = await agent.query("What is the capital of France?")
print(result.text)agent = Agent(AgentConfig(system_prompt="...", runtime="thin"))
async for event in agent.stream("Explain quantum computing"):
if event.type == "text_delta":
print(event.text, end="", flush=True)agent = Agent(AgentConfig(
system_prompt="Extract user info.",
runtime="thin",
output_format={
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
},
},
))
result = await agent.query("John is 30 years old")
print(result.structured_output) # {"name": "John", "age": 30}The same API takes you from a quick single-agent script to a governed multi-agent system in production.
Anthropic, OpenAI, Google, and DeepSeek sit behind one config. Change the model with a single line — your agent code never changes.
Start with a single assistant in 3 lines. Scale to hierarchical agent graphs with governance, delegation, and DAG task boards — same API.
Persistent episodic and procedural memory across sessions, built on 14 ISP protocols you can swap at every layer — InMemory, SQLite, or Postgres.
Every capability is an independent toggle on a protocol you can replace. Explore a few:
thin · claude_sdk · deepagents · cli · openai_agents · pi_sdk. Switch the execution engine with a single config field — everything else stays put.
# same code — pick the engine that fits
Agent(AgentConfig(system_prompt="...", runtime="thin")) # built-in multi-provider loop
Agent(AgentConfig(system_prompt="...", runtime="claude_sdk")) # Claude Agent SDK + MCP
Agent(AgentConfig(system_prompt="...", runtime="deepagents")) # LangGraph graph runtime
Agent(AgentConfig(system_prompt="...", runtime="openai_agents")) # OpenAI Agents SDKCompose org charts with a builder DSL — roots, children, delegation, and a task board with DAG dependencies and budget gates.
await (GraphBuilder(store)
.add_root("lead", "Lead", "lead", system_prompt="You lead.")
.add_child("researcher", "lead", "Researcher", "researcher")
.add_child("coder", "lead", "Coder", "coder")
.build())
run_id = await orchestrator.start("Build a REST API for user management")
result = await orchestrator.wait_for_task(f"root-{run_id}")InMemory, SQLite, and PostgreSQL providers share the same 8 protocols. Prototype in memory, ship on Postgres — no code change. Episodic + procedural recall built in.
from swarmline.memory import (
InMemoryMemoryProvider, SQLiteMemoryProvider, PostgresMemoryProvider,
)
memory = InMemoryMemoryProvider() # dev
memory = SQLiteMemoryProvider(db_path="./agent.db") # single-user
memory = PostgresMemoryProvider(session_factory) # productionDefine tools with @tool — the JSON Schema is inferred from your type hints. A default-deny policy, PreToolUse / PostToolUse hooks, and a middleware chain keep execution under control.
@tool(name="word_count", description="Count the words in a text")
async def word_count(text: str) -> str:
return str(len(text.split()))
agent = Agent(AgentConfig(
system_prompt="You are a writing assistant.",
runtime="thin",
tools=(word_count,),
))Most frameworks cover a slice. Swarmline gives you providers, orchestration, memory, and architecture in one place.
| Capability | Swarmline | LangGraph | CrewAI | AutoGen | DeepAgents | Pydantic AI | OpenAI Agents | Claude Code SDK |
|---|---|---|---|---|---|---|---|---|
| Multi-provider (4+ LLMs) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · |
| Hierarchical agent graph | ✓ | ~ | · | ~ | ✓ | ~ | · | · |
| Agent governance & delegation | ✓ | · | · | · | · | · | · | · |
| Knowledge bank + search | ✓ | · | · | · | · | · | · | · |
| Episodic + procedural memory | ✓ | · | ~ | · | ~ | · | · | · |
| Pipeline + budget gates | ✓ | · | · | ~ | · | · | · | · |
| Clean Architecture (ISP) | ✓ | · | · | · | · | ~ | · | · |
| Default-deny tool security | ✓ | · | · | · | · | · | · | ✓ |
| Swappable storage backends | ✓ | ~ | · | · | ~ | · | · | · |
| 3-line quick start | ✓ | · | ✓ | · | ~ | ✓ | ✓ | ✓ |
Comparison reflects built-in capabilities at time of writing. See thedocs for the full matrix and caveats.
Every capability is an independent toggle, built on a protocol you can swap. Turn on only what your agent needs.
Isolated file I/O and command execution — bash, read, write, edit, glob, grep. Host execution stays opt-in.
Pluggable search and fetch — DuckDuckGo, Tavily, Brave, Jina, Crawl4AI — behind one interface.
Episodic + procedural recall across sessions, consolidated into a searchable knowledge bank.
Default-deny allowlists, PreToolUse / PostToolUse hooks, and a pluggable middleware chain.
Step-by-step task decomposition and execution — plan, status, and run as first-class tools.
Structured JSON logs via structlog, OpenTelemetry export, and an activity audit trail.
Measure agent quality with custom scorers, compare/history, and console + JSON reporters.
Approval patterns at the tool, plan, and output level — keep a human in control where it matters.
No boilerplate, no graph wiring to learn first — start simple and grow into the rest.
Pull the core plus the lightweight built-in runtime.
pip install swarmline[thin]Any provider works — swap it later with one config change.
export ANTHROPIC_API_KEY=sk-ant-...Three lines to a working agent. Then just run the file.
python agent.py# agent.py
import asyncio
from swarmline import Agent, AgentConfig
agent = Agent(AgentConfig(
system_prompt="You are a helpful assistant.",
runtime="thin",
))
async def main():
result = await agent.query("Give me 3 ideas for a weekend project.")
print(result.text)
asyncio.run(main())