TFrameX (The Extensible Task & Flow Orchestration Framework for LLMs) is a Python framework designed to build sophisticated, multi-agent LLM applications with complex workflows. This document provides a comprehensive overview of the framework's architecture, design patterns, and core components.
- Core Architecture
- Component Overview
- Design Patterns
- Data Flow
- Extension Points
- Integration Architecture
┌─────────────────────────────────────────────────────────────────┐
│ TFrameX Application │
├─────────────────┬─────────────────┬─────────────────┬───────────┤
│ Agent Layer │ Flow Layer │ Tool Layer │ MCP Layer │
├─────────────────┼─────────────────┼─────────────────┼───────────┤
│ • LLMAgent │ • Flow │ • Native Tools │ • Manager │
│ • ToolAgent │ • Patterns │ • Meta Tools │ • Servers │
│ • BaseAgent │ • FlowContext │ • Agent-as-Tool │ • Connectors│
├─────────────────┴─────────────────┴─────────────────┴───────────┤
│ Runtime Context & Engine │
├─────────────────────────────────────────────────────────────────┤
│ LLM Layer │
│ • OpenAI API • Local Models • Plugins │
├─────────────────────────────────────────────────────────────────┤
│ Memory Layer │
│ • In-Memory • Custom Stores │
└─────────────────────────────────────────────────────────────────┘
- Modularity: Clear separation of concerns between components
- Extensibility: Plugin architecture for LLMs, memory stores, and tools
- Composability: Agents, patterns, and flows can be nested and combined
- Asynchronicity: Full async/await support throughout the stack
- Type Safety: Pydantic models for reliable data handling
The central registry and configuration manager for the entire framework.
Key Responsibilities:
- Agent and tool registration via decorators
- Default LLM and memory store configuration
- Runtime context creation
- MCP server management
Key Methods:
@app.agent(name="MyAgent", tools=["tool1"], mcp_tools_from_servers=["server1"])
@app.tool(name="my_tool", description="...")
app.register_flow(flow_instance)
app.run_context(llm_override=None)Manages the execution environment for agents and flows with proper resource lifecycle management.
Key Responsibilities:
- LLM client lifecycle management
- MCP server initialization and cleanup
- Flow and agent execution coordination
- Resource cleanup on context exit
Usage Pattern:
async with app.run_context() as rt:
response = await rt.call_agent("AgentName", message)
flow_result = await rt.run_flow("FlowName", initial_message)Core execution engine that manages agent instantiation, tool routing, and execution.
Key Responsibilities:
- Lazy agent instantiation with dependency resolution
- LLM instance resolution (Agent → Context → App)
- Tool routing and execution
- Agent-as-tool orchestration
Tool Routing Logic:
- MCP meta-tools (prefixed with
tframex_) - MCP server tools (prefixed with
server_alias__) - Native TFrameX tools
- Callable agents
Abstract base class providing common functionality:
class BaseAgent:
def __init__(self, agent_id, llm, tools, memory, callable_agent_definitions, **config):
self.agent_id = agent_id
self.llm = llm
self.tools = tools # Dict[str, Tool]
self.memory = memory
self.callable_agent_definitions = callable_agent_definitions
self.config = config
async def run(self, input_message, **kwargs) -> Message:
# Abstract method to be implemented by subclasses
pass
def _render_system_prompt(self, **template_vars) -> Message:
# Template variable substitution
pass
def _post_process_llm_response(self, response) -> Message:
# Think tag stripping and post-processing
passPrimary agent type for LLM-based decision making:
Key Features:
- Iterative tool calling with configurable max iterations
- MCP tool integration
- Memory management
- Error handling and fallbacks
Execution Flow:
- Add user message to memory
- Render system prompt with template variables
- Prepare tool definitions (native + MCP + callable agents)
- Call LLM with messages and tools
- Process tool calls iteratively
- Return final response
Lightweight agent for direct tool execution without LLM involvement.
Defines sequences of operations with step-by-step execution:
flow = Flow(flow_name="MyFlow", description="...")
flow.add_step("AgentName")
flow.add_step(PatternInstance)Carries state between flow steps:
class FlowContext:
current_message: Message # Output of last step
history: List[Message] # All flow messages
shared_data: Dict[str, Any] # Step-to-step data sharingReusable multi-agent interaction templates:
- SequentialPattern: Execute tasks in order
- ParallelPattern: Execute tasks concurrently
- RouterPattern: Dynamic routing based on agent decision
- DiscussionPattern: Multi-round agent discussions
@app.tool(description="Tool description")
async def my_tool(param1: str, param2: int = 5) -> str:
return f"Result: {param1} * {param2}"- Automatic schema inference from function signatures
- Type hint processing for parameter validation
- OpenAI function calling format compatibility
Agents can call other registered agents as tools:
@app.agent(callable_agents=["SpecialistAgent"])
async def supervisor_agent():
passclass BaseMemoryStore:
async def add_message(self, message: Message) -> None
async def get_history(self, limit: Optional[int] = None) -> List[Message]
async def clear(self) -> NoneDefault implementation with:
- Rolling window support
- Role-based filtering
- Message limit enforcement
class BaseLLMWrapper:
async def chat_completion(self, messages: List[Message], **kwargs) -> Message
async def close(self) -> None
@property
def model_id(self) -> strProduction-ready implementation supporting:
- OpenAI API compatibility
- Local server support (Ollama, LiteLLM)
- Streaming and non-streaming responses
- Tool calling integration
- Robust error handling with retries
- LLM resolution: Agent override → Context override → App default
- Memory resolution: Agent override → App factory
- Tool resolution: Engine resolves from app registry
Clean registration API:
@app.agent(name="MyAgent", tools=["tool1"])
@app.tool(description="My tool")- Pluggable LLM providers
- Custom memory stores
- Extensible tool system
- BaseAgent defines execution template
- Subclasses implement specific behavior
- Common post-processing in base class
- Flows contain patterns and agents
- Patterns can contain other patterns
- Hierarchical task decomposition
User Input → Runtime Context → Engine → Agent Instance
↓
Template Variables → System Prompt Rendering
↓
Memory Retrieval → Message Preparation → LLM Call
↓
Tool Call Processing → Engine Tool Routing → Tool Execution
↓
Tool Results → Memory Update → Response Post-processing
↓
Final Response ← Runtime Context ← Engine ← Agent Instance
Initial Message → Flow → Step 1 (Agent/Pattern)
↓
FlowContext Update → Step 2 (Agent/Pattern)
↓
FlowContext Update → ... → Final Step
↓
Final FlowContext ← Flow ← Last Step
Extend BaseAgent or LLMAgent:
class CustomAgent(BaseAgent):
async def run(self, input_message, **kwargs):
# Custom logic
passImplement BaseLLMWrapper:
class CustomLLM(BaseLLMWrapper):
async def chat_completion(self, messages, **kwargs):
# Custom LLM integration
passImplement BaseMemoryStore:
class DatabaseMemoryStore(BaseMemoryStore):
async def add_message(self, message):
# Database persistence
passSimple function decoration:
@app.tool()
async def custom_tool(param: str) -> str:
# Tool implementation
return resultExtend pattern classes:
class CustomPattern(BasePattern):
async def execute(self, context, engine):
# Custom execution logic
passThe Model Context Protocol (MCP) integration adds external service connectivity:
TFrameX Application
├── MCP Manager
│ ├── Server Connectors (stdio, HTTP)
│ ├── Tool Aggregation
│ └── Resource/Prompt Management
├── Meta Tools (tframex_list_mcp_servers, etc.)
└── Agent MCP Configuration
Key Integration Points:
- App Level: MCP manager initialization and lifecycle
- Agent Level: MCP tool selection and configuration
- Engine Level: MCP tool routing and execution
- Runtime Level: MCP server connection management
TFrameX supports multiple integration patterns:
- Native Tools: Direct Python function integration
- MCP Servers: Standardized protocol for external services
- Agent-as-Tool: Internal agent delegation
- API Integration: HTTP/REST service calls via tools
- Agents instantiated only when needed
- Per-context agent instances for isolation
- On-demand tool resolution
- Parallel pattern execution
- Async/await throughout
- Non-blocking I/O operations
- Automatic LLM client cleanup
- MCP connection pooling
- Memory store optimization
- Agent instance caching per context
- Tool definition caching
- Template compilation caching
- Pydantic model validation
- Tool parameter sanitization
- Template variable escaping
- Per-context agent instances
- Tool execution sandboxing
- Memory isolation between contexts
- Environment variable usage
- Secure MCP server configuration
- No credential logging
This architecture provides a robust, extensible foundation for building sophisticated multi-agent LLM applications while maintaining clean separation of concerns and supporting various integration patterns.