A deterministic, intent-based AI agent orchestrator with no restrictions. Supports any framework and prioritizes a human-reasoning approach.
Humans should handle the reasoning. AI should detect intent and translate natural language into processable data.
Traditional development has successfully solved complex problems across every industry using deterministic code, APIs, and events. The real limitation isn't in execution, it's in translation. What if we could accept natural language and automatically route to the right logic?
PyBotchi takes a different approach from most AI frameworks: LLMs excel at understanding intent and translating between human and computer language, not at business logic, calculations, or deterministic execution. Let each do what it does best.
- Detect & Translate (LLM Layer) - Process natural language to extract intents and identify appropriate Actions with arguments
- Execute Logic (Your Code) - Traditional code handles business logic, calculations, and data processing
- Generate Response (LLM Layer) - Transform processed results back into natural language
Nested Intent-Based Supervisor Agent Architecture built on just 3 core classes:
Action- The central agent with a defined lifecycle for intent and execution logicContext- Universal container for conversational state, metadata, and execution contextLLM- Singleton client for managing your model connection
This minimal foundation ensures extreme speed, efficiency, and maximum customizability.
Only 3 core classes to master. The entire system is built on a minimal foundation that minimizes overhead while maximizing performance.
Built on Pydantic BaseModel for rigorous data validation and industry-standard type hinting. Every component is inherently overridable and extendable.
Automatic JSON Schema conformance for OpenAI, Gemini, and other LLM providers. Easily adaptable to any provider's specification.
Fine-grained control over execution stages with overridable hooks: pre, post, on_error, fallback, child_selection, and commit_context.
Async-first architecture with built-in support for distributed execution via gRPC. Deploy agents remotely or across machines for massive parallel workloads.
Agents are isolated, self-contained units. Different teams can independently develop, improve, or modify specific agents without impacting core logic.
Structured parent-child relationships provide clear visibility into system execution and state, simplifying debugging and testing.
Works with any LLM client, third-party framework, or business requirement. True agnosticism through complete overridability.
Full integration with Model Context Protocol. Expose your Actions as MCP tools or consume external MCP servers within your workflows.
PyBotchi requires Python 3.12 or higher.
pip install pybotchi
# With gRPC support for distributed execution
pip install pybotchi[grpc]
# With MCP support for Model Context Protocol
pip install pybotchi[mcp]
# With both
pip install pybotchi[grpc,mcp]from langchain_openai import ChatOpenAI
from pybotchi import LLM
LLM.add(base=ChatOpenAI(
api_key="your-api-key",
model="gpt-4",
temperature=0.7,
))from pybotchi import Action
from pydantic import Field
class Translation(Action):
"""Translate to specific language."""
message: str = Field(description="The text content to be translated.")
language: str = Field(description="The ISO code or name of the target language.")
async def pre(self, context):
message = await context.llm.ainvoke(f"Reply only with translation of `{self.message}` to {self.language}.")
await context.add_response(self, message.text)
class MathProblem(Action):
"""Solve math problems."""
answer: str = Field(description="The answer to the math problem")
async def pre(self, context):
await context.add_response(self, self.answer)from pybotchi import Action
class MultiAgent(Action):
"""AI Assistant for solving math problems and translation."""
class SolveMath(MathProblem):
pass
class Translate(Translation):
passimport asyncio
from pybotchi import Context
async def test():
context = Context(
prompts=[
{"role": "system", "content": "You're an AI that can solve math problems and translate requests."},
{"role": "user", "content": "4 x 4 then explain in Filipino"},
],
)
await context.start(MultiAgent)
print(f"MathProblem: {context.prompts[-3]['content']}")
print(f"Translate: {context.prompts[-1]['content']}")
asyncio.run(test())Result:
MathProblem: Four multiplied by four is sixteen. Imagine you have four groups, and each group has four candies. If you count all the candies together, you will have sixteen candies. That's what 4 x 4 means!
Translate: Ang apat na pinarami sa apat ay labing-anim. Ipagpalagay mong may apat na grupo, at bawat grupo ay may apat na kendi. Kung bibilangin mo lahat ng kendi, magkakaroon ka ng labing-anim na kendi. Iyan ang ibig sabihin ng 4 x 4!
import asyncio
from pybotchi import graph
async def print_mermaid_graph():
multi_agent_graph = await graph(MultiAgent)
print(multi_agent_graph.flowchart())
asyncio.run(print_mermaid_graph())Result:
flowchart TD
__main__.MultiAgent.SolveMath[SolveMath]
__main__.MultiAgent{MultiAgent}
__main__.MultiAgent.Translate[Translate]
__main__.MultiAgent --> __main__.MultiAgent.SolveMath
__main__.MultiAgent --> __main__.MultiAgent.Translate
style __main__.MultiAgent fill:#4CAF50,color:#000000
Every Action follows a structured lifecycle that gives you complete control over execution flow:
Lifecycle hooks return ActionResult (ActionReturn | None). The value controls what happens next:
None(or omit return): continue normally, nothing is interruptedActionReturn.END: stop only this action's remaining lifecycle; siblings at the same level continue unaffectedActionReturn.BREAK: stop this action and break the nearest ancestor's__max_iteration__loop; also stops subsequent siblingsActionReturn.STOP: stop the entire agent immediately, propagating through all ancestorsActionReturn.stop(value=...): same as STOP but carries a return value accessible aftercontext.start()
Executes before child agents run. Use for:
- Guardrails and validation
- Data gathering (RAG, knowledge graphs)
- Business logic and preprocessing
- Tool execution
Determines which child agents to execute. Override with:
- Traditional control flow (if/else, switch/case)
- Custom LLM routing logic
- Dynamic agent selection
Executes after all child agents complete. Use for:
- Result consolidation
- Data persistence
- Cleanup and recording
- Logging and notifications
Handle errors when a child action fails to initialize (e.g. Pydantic validation on LLM tool arguments):
- Feed the error back to the LLM so it can retry on the next iteration
- Record the failed tool call in action history
- Return
Noneto skip the failed action and continue the loop
Handle errors during execution with:
- Retry mechanisms
- Custom error handling
- Logging and alerts
- Re-raise for parent handling
Executes when no child agent is selected:
- Process text content results
- Handle non-tool-call responses
- Default behaviors
Controls context merging with main execution:
- Selective data propagation
- Isolated execution contexts
- Custom synchronization rules
Executes when the __max_iteration__ limit is reached:
- Finalize and return the best available response
- Raise max-iteration-related errors
- Trigger fallback or summarization logic
- Custom additional processing
pre_mcp- MCP connection setup (authentication, config)pre_grpc- gRPC connection setup (credentials, metadata)
class CustomAgent(MultiAgent):
SolveMath = None # Remove action
class NewAction(Action): # Add new action
pass
class Translate(Translation): # Override existing
async def pre(self, context):
# Custom translation logic
passMultiple agents execute in order via iteration or multi-tool calls.
Parallel execution using async patterns. Set __concurrent__ = True on the child actions to run them in parallel:
class ParallelAgent(Action):
class Task1(Action):
__concurrent__ = True
class Task2(Action):
__concurrent__ = TrueBuild complex hierarchical structures:
class ComplexAgent(Action):
class StoryTelling(Action):
class HorrorStory(Action):
pass
class ComedyStory(Action):
pass
class JokeTelling(Action):
passScale your agents across multiple servers with real-time context synchronization:
server.py
from pybotchi import Action
from pydantic import Field
class MathProblem(Action):
"""Solve math problems."""
__groups__ = {"grpc": {"group-1"}}
answer: str = Field(description="The answer to the math problem")
async def pre(self, context):
await context.add_response(self, self.answer)client.py
from asyncio import run
from pybotchi.grpc import GRPCAction, GRPCConnection, graph
class MultiAgent(GRPCAction):
__grpc_connections__ = [GRPCConnection("remote", "localhost:50051", ["group-1"])]
async def pre_grpc(self, context):
print("Executed pre grpc connection!")
async def print_mermaid_graph():
multi_agent_graph = await graph(MultiAgent, integrations={"remote": {}})
print(multi_agent_graph.flowchart())
run(print_mermaid_graph())- Unified Graph Execution - Remote Actions integrate seamlessly
- Zero-Overhead Synchronization - No polling loops or coordination overhead
- Database-Free Architecture - Context syncs directly through gRPC
- Concurrent Remote Execution - True distributed parallel processing
- Resource Isolation - Separate compute resources per Action group
Start gRPC server:
pybotchi-grpc server.pyResult
#-------------------------------------------------------#
# Agent ID: agent_8b3c5685c84b4602966d1b3252916aa7
# Agent Path: server.py
# Starting None worker(s) on 0.0.0.0:50051
#-------------------------------------------------------#
# Agent Process: Process-1 [173012]
# Agent Handler: PyBotchiGRPC
#-------------------------------------------------------#gRPC client print graph:
python3 client.pyflowchart TD
grpc.agent_8b3c5685c84b4602966d1b3252916aa7.MathProblem[MathProblem]
__main__.MultiAgent[MultiAgent]
__main__.MultiAgent --"`**GRPC** : remote`"--> grpc.agent_8b3c5685c84b4602966d1b3252916aa7.MathProblem
style __main__.MultiAgent fill:#4CAF50,color:#000000Integrate with the MCP ecosystem. Expose Actions as MCP tools or consume external MCP servers:
server.py
from pybotchi import Action
from pybotchi.mcp import build_mcp_app
from pydantic import Field
class MathProblem(Action):
__groups__ = {"mcp": {"group-1"}}
answer: str = Field(description="The answer to the math problem")
async def pre(self, context):
await context.add_response(self, self.answer)
app = build_mcp_app(transport="streamable-http")client.py
from asyncio import run
from pybotchi.mcp import MCPAction, MCPConnection, graph
class MultiAgent(MCPAction):
__mcp_connections__ = [MCPConnection("remote", "SHTTP", "http://localhost:8000/group-1/mcp")]
# __mcp_connections__ = [MCPConnection("jira", "SSE", "https://mcp.atlassian.com/v1/sse")]
async def pre_mcp(self, context):
print("Executed pre mcp connection!")
async def print_mermaid_graph():
multi_agent_graph = await graph(MultiAgent, integrations={"remote": {}})
print(multi_agent_graph.flowchart())
run(print_mermaid_graph())- Standard Protocol Support - Full MCP specification compatibility
- Group-Based Organization - Fine-grained access control per endpoint
- Bidirectional Integration - Serve or consume MCP tools
- Transport Flexibility - SSE and Streamable HTTP support
Start MCP server:
uvicorn server:appResult
INFO: Started server process [6330]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)MCP client print graph:
python3 client.pyflowchart TD
__main__.MultiAgent[MultiAgent]
mcp.remote.MathProblem[MathProblem]
__main__.MultiAgent --"`**MCP** : remote`"--> mcp.remote.MathProblem
style __main__.MultiAgent fill:#4CAF50,color:#000000Explore practical examples demonstrating PyBotchi's capabilities:
tiny.py- Minimal implementationfull_spec.py- Complete feature demonstration
sequential.py- Sequential action executionnested_combination.py- Complex nested structures
concurrent_combination.py- Async parallel executionconcurrent_threading_combination.py- Multi-threaded processing
grpc/grpc_pybotchi_agent.py- gRPC server setupgrpc/grpc_pybotchi_client.py- Distributed orchestration
mcp/mcp_pybotchi_agent.py- MCP server implementationmcp/mcp_pybotchi_client.py- MCP client integrationmcp/mcp_pybotchi_client_for_mcp_atlassian.py- Atlassian MCP integration
interactive_action.py- Real-time WebSocket communication
vs/pybotchi_approach.py- PyBotchi implementationvs/langgraph_approach.py- LangGraph comparison
Maximum flexibility, zero lock-in. Build agents that combine human intelligence with AI precision.
Perfect for teams that need:
- Modular, maintainable agent architectures
- Framework flexibility and migration capabilities
- Community-driven agent development
- Enterprise-grade customization and control
- Real-time interactive agent communication
- Distributed execution without complexity
- Standard protocol integration (MCP)
PyBotchi passes only the tools relevant to the current intent during child selection, reducing LLM noise. Anthropic models have a constraint that conflicts with this: once a tool_use / tool_result pair for a given tool appears in the conversation history, Anthropic requires that tool's schema to be included in every subsequent API call — even if the tool is no longer relevant. This can cause validation errors in multi-level agent graphs.
OpenAI does not have this restriction.
Workarounds (choose one):
- 1-level deep agent — Keep all child actions under a single parent so every call includes all schemas.
add_messageinstead ofadd_response— Write plain assistant messages to avoid tool-call entries in history.- Custom
child_selection— Override to re-inject previously-used tool schemas alongside the active ones.
See the full documentation for code examples of each approach.
Visit our full documentation for:
- Detailed lifecycle hook explanations
- Advanced patterns and best practices
- gRPC and MCP integration guides
- Complete API reference
We welcome contributions! Whether it's:
- Bug reports and feature requests
- Documentation improvements
- Code contributions
- Example applications
Check out our contributing guidelines to get started.
PyBotchi is released under the Apache License 2.0. See LICENSE for details.
- GitHub: amadolid/pybotchi
- Issues: Report bugs or request features
- Discussions: Join the conversation
Ready to build smarter agents? Start with the examples and join the community building the future of human-AI collaboration.



