Typer-based CLI — wraps the SDK, config-driven — swarm/cli/main.py
swarm run # run a swarm from config file or inline pattern swarm init # scaffold a swarm config file swarm validate # validate a config file without running swarm export # export a programmatic swarm to YAML config
# From config file
swarm run --config swarm.yaml "Write a market analysis"
# Inline single pattern (no config file needed)
swarm run --pattern hierarchical \
--agents coordinator,worker1,worker2 \
--provider claude \
"Analyze this codebase for security issues"
# With API key
swarm run --config swarm.yaml --api-key sk-ant-... "task"
# With Ollama
swarm run --config swarm.yaml --provider ollama --model gemma3 "task"
# Output formats
swarm run --config swarm.yaml --output json "task"
swarm run --config swarm.yaml --output markdown "task"
provider:
type: claude # claude | ollama | litellm
model: claude-sonnet-4-6
auth_mode: subscription # subscription (default) | api_key
agents:
coordinator:
system_prompt: "You are a coordinator. Break tasks into subtasks."
researcher:
system_prompt: "You are a thorough researcher."
writer:
system_prompt: "You write clear, structured reports."
swarm:
- name: plan
pattern: hierarchical
agents: [coordinator, researcher]
- name: research
pattern: parallel
agents: [researcher, researcher]
after: plan
merge: synthesize
- name: write
pattern: sequential
agents: [writer]
after: research
import typer, asyncio, yaml
from swarm import Swarm, ClaudeProvider, LLMAgent
app = typer.Typer()
@app.command()
def run(
task: str,
config: Path = typer.Option(...),
api_key: str | None = typer.Option(None, envvar="ANTHROPIC_API_KEY"),
output: str = typer.Option("text"),
):
cfg = yaml.safe_load(config.read_text())
provider = build_provider(cfg["provider"], api_key)
agents = {name: LLMAgent(name, provider, **spec)
for name, spec in cfg["agents"].items()}
swarm = Swarm.from_config(cfg["swarm"], agents)
result = asyncio.run(swarm.run(task))
print_result(result, output)
if __name__ == "__main__":
app()