Overview of the included examples for the ECS-based LLM Agent framework.
| Example Name | Description | API Key Required? | Key Features |
|---|---|---|---|
| Simple Chat Agent | Minimal single-agent chat with FakeProvider | No | World + LLMComponent + Runner |
| Tool-Using Agent | LLM calls a tool, system executes it | No | ToolRegistryComponent, ToolExecutionSystem |
| Multi-Agent Collaboration | Two agents exchange messages | No | MessageBus components, MessageBusSystem |
| ReAct Pattern Agent | PlanningSystem drives multi-step plan | Yes (OpenAI) | PlanningSystem, ToolExecutionSystem |
| Plan-and-Execute Agent | Dynamic replanning based on results | Yes (OpenAI) | ReplanningSystem, RetryProvider |
| Streaming Responses | Real-time response streaming | Optional | stream=True, Delta iteration |
| Retry with Backoff | Automatic retries for transient errors | Optional | RetryProvider, RetryConfig |
| Structured Output | JSON mode with Pydantic validation | Optional | pydantic_to_response_format |
| World Serialization | Save/load world state to/from JSON | No | WorldSerializer.save/load |
| Tool Approval Agent | Policy-based tool call approval flow | No | ToolApprovalComponent, ToolApprovalSystem |
| Markdown Skill Agent | Load SKILL.md and install markdown-driven skill | Optional | MarkdownSkill, SkillManager |
| Tree Search Agent | MCTS planning for complex goals | No | PlanSearchComponent, TreeSearchSystem |
| RAG Agent | Vector search retrieval-augmented generation | No | RAGTriggerComponent, RAGSystem |
| Sub-Agent Delegation | Parent agent delegates to child agents | No | Subagent components, MessageBusSystem |
| Task Orchestration System | Dependency-aware task execution with persistence and mixed backends | No | TaskComponent, WavePlanner, TaskExecutor, Scratchbook, WorldSerializer |
| Claude Agent | Native Anthropic Claude provider | Yes (Anthropic) | ClaudeProvider |
| LiteLLM Agent | Unified access to 100+ LLM providers | Yes (varies) | LiteLLMProvider |
| System Streaming | System-level streaming with events | Optional | StreamingComponent, StreamStartEvent |
| Context Management | Checkpoint, undo, and compaction demo | Optional | CheckpointSystem, CompactionSystem |
Nine examples support dual-mode execution — automatically switching between FakeProvider (default) and OpenAIProvider (with API credentials) based on environment variables.
Dual-mode examples work in two ways:
- Fake Mode (No API Key): Uses
FakeProviderwith pre-scripted responses. Perfect for testing, demos, and learning without incurring API costs. - Real Mode (With API Key): Uses
OpenAIProviderto call your LLM API. Set environment variables to activate real mode.
These 9 examples support dual-mode:
chat_agent.py— Minimal chat with provider fallbackmulti_agent.py— Two agents collaboratingskill_discovery_agent.py— Skills auto-discoverypermission_agent.py— Permission-controlled toolsskill_agent.py— SKILL.md-based skill loading and installsubagent_delegation.py— Parent delegating to child agentstree_search_agent.py— MCTS planningcontext_management_agent.py— Checkpoint and undorag_agent.py— Retrieval-Augmented Generation
Control dual-mode behavior with these environment variables:
| Variable | Purpose | Default | Example |
|---|---|---|---|
LLM_API_KEY |
Trigger for real mode. If set, activates OpenAIProvider. If unset, uses FakeProvider. |
Unset (fake mode) | sk-... |
LLM_BASE_URL |
API endpoint (OpenAI-compatible) | https://dashscope.aliyuncs.com/compatible-mode/v1 |
https://api.openai.com/v1 |
LLM_MODEL |
LLM model name | qwen3.5-flash |
gpt-4o-mini |
EMBEDDING_MODEL |
Embedding model (RAG only) | text-embedding-v3 |
text-embedding-3-small |
EMBEDDING_DIMENSION |
Embedding vector dimension (RAG only) | 1024 |
1536 |
Run in fake mode (no API key needed):
uv run python examples/chat_agent.pyRun in real mode (requires .env with credentials):
export LLM_API_KEY=sk-your-api-key-here
export LLM_BASE_URL=https://api.openai.com/v1
export LLM_MODEL=gpt-4o-mini
uv run python examples/chat_agent.pyOr use .env file:
cp .env.example .env
# Edit .env with your credentials
uv run python examples/chat_agent.py- File:
examples/chat_agent.py - What it demonstrates: Basic agent setup using the ECS pattern with a
FakeProvider. - Run:
python examples/chat_agent.py - Pattern:
World+ entity +LLMComponent+ConversationComponent+ReasoningSystem+MemorySystem+ErrorHandlingSystem+Runner.
# Create Agent Entity
agent_id = world.create_entity()
world.add_component(agent_id, LLMComponent(provider=provider, model="fake"))
world.add_component(agent_id, ConversationComponent(messages=[Message(role="user", content="Hello!")]))
# Register Systems
world.register_system(ReasoningSystem(priority=0), priority=0)
world.register_system(MemorySystem(), priority=10)
world.register_system(ErrorHandlingSystem(priority=99), priority=99)A simple conversation printout:
Conversation:
user: Hello, how are you?
assistant: Hello! I'm doing great, thank you for asking! How can I help you today?
Dual-Mode Support: This example supports both fake and real modes. Run without
LLM_API_KEYforFakeProvider, or setLLM_API_KEYto useOpenAIProvider. See Dual-Mode Provider Selection for details.
- File:
examples/tool_agent.py - What it demonstrates: An agent that can call tools (e.g., an
addfunction). - Run:
python examples/tool_agent.py - Pattern:
ToolRegistryComponentwithToolSchemaand async handlers +ToolExecutionSystem(priority=5).
# Register tools
world.add_component(
agent_id,
ToolRegistryComponent(
tools={"add": ToolSchema(name="add", description="Add two numbers", ...)},
handlers={"add": add},
),
)
# Register Systems (ToolExecutionSystem is key)
world.register_system(ReasoningSystem(priority=0), priority=0)
world.register_system(ToolExecutionSystem(priority=5), priority=5)The agent calls the tool and then provides the final answer:
Conversation:
user: What is 2 + 3?
assistant: [tool_calls: add]
tool (tool result): 5
assistant: The answer is 5
- File:
examples/multi_agent.py - What it demonstrates: Two agents (researcher and summarizer) collaborating via pub/sub messaging.
- Run:
python examples/multi_agent.py - Pattern:
MessageBusSubscriptionComponent+MessageBusSystem(pub/sub).
# Agent A subscribes to researcher topic
world.add_component(agent_a_id, MessageBusSubscriptionComponent(subscriptions={"research.updates"}))
# Agent B publishes to researcher topic via MessageBusSystem.publish()Conversations for both agents showing messages routed via the bus:
Agent A (researcher) conversation:
user: Start researching the topic.
assistant: I've analyzed the data and found interesting patterns.
Agent B (summarizer) conversation:
assistant (from researcher on research.updates): I found interesting data.
assistant: Thank you! I'll summarize the key findings for you.
Dual-Mode Support: This example supports both fake and real modes. Run without
LLM_API_KEYforFakeProvider, or setLLM_API_KEYto useOpenAIProvider. See Dual-Mode Provider Selection for details.
- File:
examples/serialization_demo.py - What it demonstrates: Saving and loading the entire world state to/from JSON.
- Run:
python examples/serialization_demo.py - Pattern:
WorldSerializer.save(world, path)→WorldSerializer.load(path, providers={...}, tool_handlers={...}).
# Save World to JSON
WorldSerializer.save(world, "world_state.json")
# Load World from JSON
loaded_world = WorldSerializer.load(
"world_state.json",
providers={"fake-model": provider},
tool_handlers=tool_handlers,
)Verification that loaded state matches original:
STEP 2: SAVE WORLD TO JSON
✓ World saved to world_state.json
✓ JSON contains 3 entities
STEP 3: LOAD WORLD FROM JSON
✓ World loaded from world_state.json
STEP 4: VERIFY LOADED STATE
✓ All checks passed!
- File:
examples/task_orchestration_system.py - What it demonstrates: Dependency analysis, wave-based dispatch, local and subagent task routing, task snapshots/event logs, scratchbook result indexing, and world serialization roundtrip in one deterministic demo.
- Run:
uv run python examples/task_orchestration_system.py - Pattern:
TaskComponent+analyze_task_dependencies()+WavePlanner+TaskFetchingUnit+TaskExecutor+TaskPersistenceService+WorldSerializer.save/load().
Task waves, completed tasks, and a final generated brief:
Task orchestration waves:
Wave 1: collect_requirements, background_research
Wave 2: draft_execution_plan
Wave 3: risk_review, publish_brief
Completed tasks: collect_requirements, background_research, draft_execution_plan, risk_review, publish_brief
Final brief: write_brief: packaged final brief ...
- File:
examples/react_agent.py - What it demonstrates: The full Reasoning + Acting (ReAct) pattern with a multi-step plan.
- Run:
uv run python examples/react_agent.py - Required Env:
LLM_API_KEY,LLM_BASE_URL,LLM_MODEL. - Pattern:
PlanComponent+PlanningSystem+ToolExecutionSystem+PlanStepCompletedEventsubscription.
# Attach plan steps
plan_steps = ["Look up weather in Beijing", "Look up population in Beijing", ...]
world.add_component(main_agent, PlanComponent(steps=plan_steps))
# Register systems (order: planning -> tool execution)
world.register_system(PlanningSystem(priority=0), priority=0)
world.register_system(ToolExecutionSystem(priority=5), priority=5)
# Subscribe to progress
world.event_bus.subscribe(PlanStepCompletedEvent, on_step_completed)Step-by-step progress and final comparison:
Running ReAct agent with 5-step plan...
✓ Step 1 completed: Look up the weather in Beijing...
✓ Step 2 completed: Look up the weather in Shanghai...
...
[Thought] Based on the data, Beijing is cooler but larger...
- File:
examples/plan_and_execute_agent.py - What it demonstrates: Dynamic replanning where the agent revises its plan after each step.
- Run:
uv run python examples/plan_and_execute_agent.py - Required Env:
LLM_API_KEY, timeouts, and retries. - Pattern:
PlanningSystem+ToolExecutionSystem+ReplanningSystem+RetryProvider+PlanRevisedEvent.
# Wrap provider with retry logic
provider = RetryProvider(base_provider, retry_config=RetryConfig(max_attempts=3))
# Register systems including ReplanningSystem
world.register_system(PlanningSystem(priority=0), priority=0)
world.register_system(ToolExecutionSystem(priority=5), priority=5)
world.register_system(ReplanningSystem(priority=7), priority=7)
# Subscribe to replanning events
world.event_bus.subscribe(PlanRevisedEvent, on_plan_revised)Initial plan steps followed by potential revisions:
Running Plan-and-Execute agent...
✓ Step 1 completed: Check weather for Beijing...
📋 Plan revised!
Old plan: [...]
New plan: [...]
- File:
examples/streaming_agent.py - What it demonstrates: Real-time character-by-character or word-by-word output from an LLM.
- Run:
uv run python examples/streaming_agent.py - Pattern:
async for delta in delta_iterator: sys.stdout.write(delta.content).
# Call provider with streaming enabled
delta_iterator = await provider.complete(messages, stream=True)
# Print chunks in real-time
async for delta in delta_iterator:
if delta.content:
sys.stdout.write(delta.content)
sys.stdout.flush()
# Access usage stats from final delta
if delta.finish_reason:
print(f"Total tokens: {delta.usage.total_tokens}")The response appearing gradually:
Streaming response:
------------------------------------------------------------
Streaming in LLMs refers to the technique where...
------------------------------------------------------------
Tokens used:
Prompt tokens: 15
Completion tokens: 35
Total tokens: 50
- File:
examples/retry_agent.py - What it demonstrates: Automatic retries for transient HTTP errors like 429 or 500.
- Run:
uv run python examples/retry_agent.py - Pattern:
RetryProviderwrapping a base provider with a customRetryConfig.
# Custom retry config
retry_config = RetryConfig(
max_attempts=5,
multiplier=2.0,
min_wait=2.0,
max_wait=30.0,
retry_status_codes=(429, 500, 502, 503, 504),
)
# Wrap provider
provider = RetryProvider(base_provider, retry_config=retry_config)Logs showing retry attempts (if errors occur) and the final successful completion:
Retry Configuration:
max_attempts: 5
multiplier: 2.0
...
Completion Result:
Role: assistant
Content: This is a demonstration response...
✓ Completion succeeded
- File:
examples/structured_output_agent.py - What it demonstrates: Extracting JSON data that strictly follows a Pydantic model.
- Run:
uv run python examples/structured_output_agent.py - Pattern:
pydantic_to_response_format(CityInfo)→provider.complete(messages, response_format=...).
# Convert Pydantic model to response format
response_format = pydantic_to_response_format(CityInfo)
# Call LLM with JSON mode enabled
result = await provider.complete(messages, response_format=response_format)
# Parse and validate JSON back into Pydantic model
city_info = CityInfo.model_validate_json(result.message.content)
print(f"City: {city_info.name}, Population: {city_info.population}M")Formatted data extracted from the JSON response:
STRUCTURED OUTPUT RESULT
============================================================
City Name: Tokyo
Country: Japan
Population: 14.0 million
Climate: Temperate
Landmarks:
- Senso-ji Temple
- Tokyo Tower
...
- File:
examples/tool_approval_agent.py - What it demonstrates: Policy-based manual approval flow for sensitive tool calls.
- Run:
uv run python examples/tool_approval_agent.py - Pattern:
ToolApprovalComponent+ToolApprovalSystem.
- File:
examples/skill_agent.py - What it demonstrates: Loading a markdown skill from
SKILL.md, auto-discovering script-based tools, and installing it withSkillManager. - Run:
uv run python examples/skill_agent.py - Pattern:
Skill+SkillManager+ReasoningSystem.
Dual-Mode Support: This example supports both fake and real modes. Run without
LLM_API_KEYforFakeProvider, or setLLM_API_KEYto useOpenAIProvider. See Dual-Mode Provider Selection for details.
- File:
examples/tree_search_agent.py - What it demonstrates: MCTS planning for complex goals using Monte Carlo Tree Search.
- Run:
uv run python examples/tree_search_agent.py - Pattern:
PlanSearchComponent+TreeSearchSystem.
Dual-Mode Support: This example supports both fake and real modes. Run without
LLM_API_KEYforFakeProvider, or setLLM_API_KEYto useOpenAIProvider. See Dual-Mode Provider Selection for details.
- File:
examples/rag_agent.py - What it demonstrates: Retrieval-augmented generation using vector search.
- Run:
uv run python examples/rag_agent.py - Pattern:
RAGTriggerComponent+RAGSystem+EmbeddingComponent+VectorStoreComponent.
Dual-Mode Support: This example supports both fake and real modes. Run without
LLM_API_KEYforFakeProvider, or setLLM_API_KEY+EMBEDDING_MODEL+EMBEDDING_DIMENSIONto use real embedding providers. See Dual-Mode Provider Selection for details.
- File:
examples/subagent_delegation.py - What it demonstrates: Parent agent delegating tasks via
delegatetool with SubagentSystem managing child execution, state inheritance policy, and explicit tool installation. - Run:
uv run python examples/subagent_delegation.py - Pattern:
SubagentRegistryComponent+SubagentSystem+InheritancePolicy.
# Define subagent with inheritance policy
researcher = SubagentConfig(
name="researcher",
provider=provider,
inheritance_policy=InheritancePolicy(inherit_system_prompt=True)
)
# Optional: Explicitly install delegate tool with custom name
subagent_system = SubagentSystem()
subagent_system.install_delegate_tool(world, parent_id, tool_name="delegate")- File:
examples/subagent_delegation.py - What it demonstrates: Parent agent delegating tasks via
delegatetool with SubagentSystem managing child execution and skill inheritance. - Run:
uv run python examples/subagent_delegation.py - Pattern:
SubagentRegistryComponent+SubagentSystem(auto-registersdelegatetool) + skill inheritance configuration.
# SubagentSystem auto-registers the delegate tool for entities with registry.
# If a subagent has 'skills' defined, they are inherited from the parent.
world.register_system(SubagentSystem(priority=-1), priority=-1)- What it demonstrates: Parent agent delegating tasks via
delegatetool. SubagentSystem manages child execution. - Run:
uv run python examples/subagent_delegation.py - Pattern:
SubagentRegistryComponent+SubagentSystem(auto-registersdelegatetool).
# SubagentSystem auto-registers the delegate tool
# Parent LLM calls delegate → SubagentSystem executes child → result returnedDual-Mode Support: This example supports both fake and real modes. Run without
LLM_API_KEYforFakeProvider, or setLLM_API_KEYto useOpenAIProvider. See Dual-Mode Provider Selection for details.
- File:
examples/claude_agent.py - What it demonstrates: Native usage of the Anthropic Claude provider.
- Run:
uv run python examples/claude_agent.py - Pattern:
ClaudeProvider.
- File:
examples/litellm_agent.py - What it demonstrates: Unified access to 100+ LLM providers.
- Run:
uv run python examples/litellm_agent.py - Pattern:
LiteLLMProvider.
- File:
examples/streaming_system_agent.py - What it demonstrates: System-level streaming using the event bus.
- Run:
uv run python examples/streaming_system_agent.py - Pattern:
StreamingComponent+StreamStartEvent+StreamReasoningDeltaEvent+StreamReasoningEndEvent+StreamContentStartEvent+StreamContentDeltaEvent+StreamEndEvent.
- File:
examples/context_management_agent.py - What it demonstrates: Checkpoint, undo, and conversation compaction lifecycle.
- Run:
uv run python examples/context_management_agent.py - Pattern:
CheckpointSystem+CompactionSystem+CheckpointComponent+CompactionConfigComponent.
Dual-Mode Support: This example supports both fake and real modes. Run without
LLM_API_KEYforFakeProvider, or setLLM_API_KEYto useOpenAIProvider. See Dual-Mode Provider Selection for details.