A comprehensive suite of libraries for building production-ready AI agent systems. This monorepo contains three complementary packages that work together to provide everything from core abstractions to full-stack deployment.
- Step-by-Step Django Setup Guide - Start here for new projects
- Package Overview - What each package does
- Architecture & Boundaries - How they fit together
- API Reference - Key classes and functions
- Use Cases & Patterns - Common implementation patterns
This guide walks through setting up a complete AI agent system in an existing Django project.
- Python 3.11+
- Django 4.2+
- PostgreSQL (recommended) or SQLite
- OpenAI API key (or Anthropic)
# Install the Django runtime with recommended extras (includes OpenAI, Anthropic)
pip install django-agent-runtime[recommended]
# Or install with specific providers only
pip install django-agent-runtime agent-runtime-core[openai]Add to your settings.py:
INSTALLED_APPS = [
# ... your existing apps ...
'rest_framework',
'django_agent_runtime',
]
# Agent Runtime Configuration
DJANGO_AGENT_RUNTIME = {
# Queue backend: 'postgres' (recommended), 'memory', or 'redis'
'QUEUE_BACKEND': 'postgres',
# Event bus: 'db' (recommended), 'memory', or 'redis'
'EVENT_BUS_BACKEND': 'db',
# LLM provider: 'openai', 'anthropic', or 'litellm'
'MODEL_PROVIDER': 'openai',
# Default model to use
'DEFAULT_MODEL': 'gpt-4o',
# List of modules that register agents (called on startup)
'RUNTIME_REGISTRY': [
'myapp.agents:register_agents',
],
# Optional: Enable debug mode for detailed error messages
'DEBUG': True,
}In your urls.py:
from django.urls import path, include
urlpatterns = [
# ... your existing urls ...
path('api/agents/', include('django_agent_runtime.urls')),
]python manage.py migrateThis creates the following tables:
agent_run- Stores agent execution runsagent_conversation- Stores conversation historyagent_event- Stores events for SSE streamingstep_checkpoint- Stores checkpoints for long-running tasksstep_event- Stores step execution events
Create myapp/agents.py:
from django_agent_runtime.runtime.interfaces import (
AgentRuntime, RunContext, RunResult, EventType
)
from django_agent_runtime.runtime.registry import register_runtime
from django_agent_runtime.runtime.llm import get_llm_client
class SimpleAgent(AgentRuntime):
"""A simple conversational agent."""
@property
def key(self) -> str:
return "simple-agent"
@property
def name(self) -> str:
return "Simple Assistant"
@property
def description(self) -> str:
return "A helpful AI assistant"
async def run(self, ctx: RunContext) -> RunResult:
# Get the LLM client
llm = get_llm_client()
# Build messages with system prompt
messages = [
{"role": "system", "content": "You are a helpful assistant."},
*ctx.input_messages,
]
# Generate response
response = await llm.generate(messages)
# Emit the response as an event (for SSE streaming)
await ctx.emit(EventType.ASSISTANT_MESSAGE, {
"content": response.message["content"]
})
# Return the result
return RunResult(
final_output={"response": response.message["content"]},
final_messages=[response.message]
)
def register_agents():
"""Called on Django startup to register agents."""
register_runtime(SimpleAgent())You need two processes running:
Terminal 1 - Django Server:
python manage.py runserverTerminal 2 - Agent Workers:
# Start workers to process agent runs
python manage.py runagent --processes 2 --concurrency 10# Create a new agent run
curl -X POST http://localhost:8000/api/agents/runs/ \
-H "Content-Type: application/json" \
-d '{
"agent_key": "simple-agent",
"input": {
"messages": [{"role": "user", "content": "Hello!"}]
}
}'
# Response includes run_id for SSE streaming
# {"id": "abc123", "status": "pending", ...}
# Stream events (SSE)
curl http://localhost:8000/api/agents/runs/abc123/events/Add to your HTML template:
<!-- Include the widget -->
<link rel="stylesheet" href="https://unpkg.com/@makemore/agent-frontend/dist/chat-widget.css">
<script src="https://unpkg.com/@makemore/agent-frontend/dist/chat-widget.js"></script>
<!-- Initialize -->
<script>
ChatWidget.init({
backendUrl: window.location.origin,
agentKey: 'simple-agent',
title: 'AI Assistant',
primaryColor: '#0066cc',
position: 'bottom-right',
apiPaths: {
runs: '/api/agents/runs/',
runEvents: '/api/agents/runs/{runId}/events/',
},
});
</script>For agents that need to call tools (APIs, databases, etc.):
from django_agent_runtime.runtime.interfaces import (
AgentRuntime, RunContext, RunResult, EventType
)
from django_agent_runtime.runtime.registry import register_runtime
from agent_runtime_core import ToolCallingAgent, ToolRegistry, Tool
class WeatherAgent(ToolCallingAgent):
"""An agent that can check the weather."""
@property
def key(self) -> str:
return "weather-agent"
@property
def system_prompt(self) -> str:
return """You are a helpful weather assistant.
Use the get_weather tool to answer questions about weather.
Always be friendly and informative."""
@property
def tools(self) -> ToolRegistry:
registry = ToolRegistry()
registry.register(Tool(
name="get_weather",
description="Get the current weather for a location",
parameters={
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name, e.g., 'London' or 'New York'"
},
"units": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature units"
}
},
"required": ["location"]
},
handler=self._get_weather,
))
return registry
async def _get_weather(self, location: str, units: str = "celsius") -> str:
# In a real app, call a weather API here
return f"The weather in {location} is sunny, 22ยฐC"
def register_agents():
register_runtime(WeatherAgent())For complex tool schemas, use the builder:
from agent_runtime_core import ToolSchemaBuilder
schema = (
ToolSchemaBuilder("search_database")
.description("Search the product database")
.param("query", "string", "Search query", required=True)
.param("category", "string", "Product category", enum=["electronics", "clothing", "books"])
.param("max_results", "integer", "Maximum results to return", default=10)
.param("filters", "object", "Additional filters")
.build()
)
# Convert to OpenAI format
openai_format = schema.to_openai_format()For agents that need to search knowledge bases:
from agent_runtime_core.vectorstore import get_vector_store, get_embedding_client
# SQLite-based vector store (good for development)
vector_store = get_vector_store("sqlite_vec", path="./vectors.db")
# Or PostgreSQL with pgvector (recommended for production)
# vector_store = get_vector_store("pgvector", connection_string="postgresql://...")
# Embedding client
embedding_client = get_embedding_client("openai")from agent_runtime_core.rag import KnowledgeIndexer, ChunkingConfig
indexer = KnowledgeIndexer(
vector_store=vector_store,
embedding_client=embedding_client,
)
# Index a document
result = await indexer.index_text(
text="Your document content here...",
source_id="doc-1",
metadata={"name": "Product Manual", "category": "documentation"},
chunking_config=ChunkingConfig(chunk_size=500, chunk_overlap=50),
)
print(f"Indexed {result.chunks_indexed} chunks")from agent_runtime_core.rag import KnowledgeRetriever
class RAGAgent(AgentRuntime):
def __init__(self):
self.retriever = KnowledgeRetriever(
vector_store=vector_store,
embedding_client=embedding_client,
)
async def run(self, ctx: RunContext) -> RunResult:
# Get user's question
user_message = ctx.input_messages[-1]["content"]
# Retrieve relevant knowledge
results = await self.retriever.retrieve(
query=user_message,
top_k=5,
similarity_threshold=0.7,
)
# Format for prompt
knowledge = self.retriever.format_results(results)
# Build prompt with knowledge
messages = [
{"role": "system", "content": f"You are a helpful assistant.\n\n{knowledge}"},
*ctx.input_messages,
]
# Generate response
llm = get_llm_client()
response = await llm.generate(messages)
await ctx.emit(EventType.ASSISTANT_MESSAGE, {
"content": response.message["content"]
})
return RunResult(
final_output={"response": response.message["content"]},
final_messages=[response.message]
)Enable agents to remember facts, preferences, and context across conversations.
from agent_runtime_core import ToolCallingAgent, ToolRegistry
from agent_runtime_core.memory import MemoryEnabledAgent, MemoryConfig
from agent_runtime_core.persistence import FileKnowledgeStore
class MyAgent(MemoryEnabledAgent, ToolCallingAgent):
"""Agent with cross-conversation memory."""
memory_enabled = True # Enable memory
memory_config = MemoryConfig(
max_memories_to_recall=10,
relevance_threshold=0.5,
)
@property
def key(self) -> str:
return "my-agent"
@property
def system_prompt(self) -> str:
return "You are a helpful assistant."
@property
def tools(self) -> ToolRegistry:
return ToolRegistry()
# Configure memory storage before running
agent = MyAgent()
agent.configure_memory(
knowledge_store=FileKnowledgeStore(),
# llm_client is optional - uses agent's LLM by default
)- Before each run: Relevant memories are recalled and injected into the system prompt
- After each run: New facts are extracted from the conversation and stored
- Memories are scoped per user: Use
user_idin context metadata
For more control, use MemoryManager directly:
from agent_runtime_core.memory import MemoryManager, MemoryConfig
from agent_runtime_core.persistence import FileKnowledgeStore
from agent_runtime_core.llm import get_llm_client
# Setup
memory = MemoryManager(
knowledge_store=FileKnowledgeStore(),
llm_client=get_llm_client(),
user_id="user-123", # Scope memories to this user
)
# Extract memories from a conversation
messages = [
{"role": "user", "content": "My name is Alice and I prefer dark mode."},
{"role": "assistant", "content": "Nice to meet you, Alice!"},
]
extracted = await memory.extract_memories(messages)
# [ExtractedMemory(key="user_name", value="Alice", fact_type=USER),
# ExtractedMemory(key="preferred_theme", value="dark", fact_type=PREFERENCE)]
# Recall memories for a new conversation
memories = await memory.recall_memories(
query="What theme does the user prefer?",
)
# [RecalledMemory(key="preferred_theme", value="dark", relevance=0.95)]
# Format for prompt inclusion
prompt_text = memory.format_memories_for_prompt(memories, format_style="list")
# "Remembered information about the user:\n- preferred_theme: dark\n- user_name: Alice"
# Manual memory operations
await memory.set_memory("favorite_color", "blue")
color = await memory.get_memory("favorite_color")
await memory.delete_memory("favorite_color")
await memory.clear_memories() # Clear all memories for userfrom agent_runtime_core.memory import MemoryConfig
from agent_runtime_core.persistence import Scope
config = MemoryConfig(
# Extraction settings
extract_after_messages=4, # Extract after N messages
extract_on_conversation_end=True,
max_facts_per_extraction=5,
# Recall settings
max_memories_to_recall=10,
relevance_threshold=0.5, # 0.0 to 1.0
# What to extract
extract_user_facts=True, # Name, role, etc.
extract_project_facts=True, # Project-specific info
extract_preferences=True, # User preferences
# Storage scope
scope=Scope.GLOBAL, # GLOBAL, PROJECT, or SESSION
)Quickly add memory to existing agents:
from agent_runtime_core.memory import with_memory
from agent_runtime_core.persistence import FileKnowledgeStore
# Original agent class
class MyAgent(ToolCallingAgent):
...
# Create memory-enabled version
MemoryMyAgent = with_memory(
MyAgent,
knowledge_store=FileKnowledgeStore(),
)
agent = MemoryMyAgent() # Memory is automatically configuredIn Django, use the database-backed knowledge store:
# In your agent
from django_agent_runtime.persistence import DjangoKnowledgeStore
class MyAgent(MemoryEnabledAgent, ToolCallingAgent):
memory_enabled = True
# ... agent properties ...
# Configure with Django store
agent = MyAgent()
agent.configure_memory(
knowledge_store=DjangoKnowledgeStore(user=request.user),
)| Package | Type | Purpose | Status | Links |
|---|---|---|---|---|
| agent_runtime_core | Python Library | Framework-agnostic core abstractions for AI agents | โ Stable (v0.7.0) | GitHub โข PyPI |
| django_agent_runtime | Django App | Production-ready Django app with API, workers, step execution, and real-time streaming | โ Production (v0.4.0) | GitHub โข PyPI |
| agent-frontend | JavaScript Library | Zero-dependency embeddable chat widget for AI agents | โ Production (v1.8.0) | GitHub โข npm |
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Frontend Layer โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ agent-frontend (JavaScript/TypeScript) โ โ
โ โ โข Embeddable chat widget (vanilla JS) โ โ
โ โ โข SSE streaming client โ โ
โ โ โข Session management โ โ
โ โ โข Zero dependencies โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ HTTP/SSE
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Django Integration Layer โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ django_agent_runtime (Django App) โ โ
โ โ โข REST API endpoints โ โ
โ โ โข SSE event streaming โ โ
โ โ โข PostgreSQL queue โ โ
โ โ โข Worker management (runagent command) โ โ
โ โ โข Database models (AgentRun, AgentConversation, etc.) โ โ
โ โ โข DjangoStepExecutor for multi-step operations โ โ
โ โ โข Database-backed checkpointing (StepCheckpoint, StepEvent)โ โ
โ โ โข Anonymous session support โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ Uses
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Core Layer (Foundation) โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ agent_runtime_core (Python Library) โ โ
โ โ โข AgentRuntime interface โ โ
โ โ โข RunContext & RunResult โ โ
โ โ โข Tool registry & execution โ โ
โ โ โข ToolCallingAgent base class โ โ
โ โ โข LLM client abstractions (OpenAI, Anthropic, LiteLLM) โ โ
โ โ โข Event system (EventType, EventBus) โ โ
โ โ โข Queue abstractions (InMemory, Redis, SQLite) โ โ
โ โ โข State store abstractions โ โ
โ โ โข Persistence layer (Conversations, Tasks, Memory) โ โ
โ โ โข RAG (chunking, indexing, retrieval) โ โ
โ โ โข VectorStore (sqlite-vec, pgvector) โ โ
โ โ โข StepExecutor for multi-step operations โ โ
โ โ โข InMemoryRunContext, FileRunContext for pure Python โ โ
โ โ โข Configuration management โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- User Interaction โ
agent-frontend(JavaScript widget in browser) - HTTP Request โ
django_agent_runtime(REST API creates AgentRun) - Queue Job โ PostgreSQL queue stores the run
- Worker Picks Up โ
runagentworker process claims the job - Agent Execution โ Your agent (using
ToolCallingAgentor customAgentRuntime) - Core Execution โ
agent_runtime_corehandles LLM calls, tools, events - Real-time Events โ SSE stream back to
agent-frontend - UI Updates โ Widget displays messages in real-time
agent-frontend (standalone, no Python deps)
โ
โโโโ HTTP/SSE โโโโ
โ
django_agent_runtime โ
โโโโ depends on: agent_runtime_core
โ
agent_runtime_core (no dependencies, optional extras for LLM providers)
Responsibility: Core abstractions and utilities (pure Python, no Django)
- โ
Agent interface (
AgentRuntime,RunContext,RunResult) - โ
Tool system (
Tool,ToolRegistry) - โ LLM clients (OpenAI, Anthropic, LiteLLM)
- โ
Event system (
EventType,EventBus) - โ Queue abstractions (memory, Redis, PostgreSQL)
- โ Persistence layer (conversations, tasks, memory)
- โ StepExecutor for multi-step operations
- โ InMemoryRunContext for testing/scripts
- โ FileRunContext for file-based persistence
- โ Configuration management
- โ No Django-specific code
- โ No web framework dependencies
- โ No frontend code
Responsibility: Production Django deployment (includes step execution)
- โ
REST API (
AgentRunViewSet,AgentConversationViewSet) - โ SSE event streaming endpoints
- โ
Database models (
AgentRun,AgentConversation,AgentEvent) - โ PostgreSQL-based queue
- โ
Worker management (
runagentcommand) - โ
DjangoStepExecutorwith database checkpointing - โ
DjangoRunContextfor ORM-backed context - โ
StepCheckpoint&StepEventmodels - โ Anonymous session support
- โ Event visibility system
- โ Debug/production mode configuration
- โ No frontend code
Responsibility: Browser-based chat UI
- โ Embeddable chat widget (vanilla JavaScript)
- โ SSE client for real-time streaming
- โ Session management
- โ Authentication strategies (token, JWT, session, anonymous)
- โ Text-to-speech integration (ElevenLabs)
- โ Demo flows and auto-run modes
- โ Markdown rendering
- โ Dark mode support
- โ No backend code
- โ No Python dependencies
- โ No agent execution logic
The main interface all agents must implement:
from agent_runtime_core import AgentRuntime, RunContext, RunResult
class MyAgent(AgentRuntime):
@property
def key(self) -> str:
"""Unique identifier for this agent."""
return "my-agent"
@property
def name(self) -> str:
"""Human-readable name."""
return "My Agent"
@property
def description(self) -> str:
"""Description of what this agent does."""
return "A helpful assistant"
async def run(self, ctx: RunContext) -> RunResult:
"""Execute the agent logic."""
# Your implementation here
passProvides context and utilities during agent execution:
class RunContext:
run_id: str # Unique ID for this run
input_messages: list[dict] # User messages [{"role": "user", "content": "..."}]
metadata: dict # Additional metadata
async def emit(self, event_type: EventType, data: dict) -> None:
"""Emit an event (for SSE streaming)."""
async def get_state(self, key: str) -> Any:
"""Get state value."""
async def set_state(self, key: str, value: Any) -> None:
"""Set state value."""Return value from agent execution:
from agent_runtime_core import RunResult
result = RunResult(
final_output={"response": "Hello!"}, # Structured output
final_messages=[{"role": "assistant", "content": "Hello!"}], # Messages to append
metadata={"tokens_used": 150}, # Optional metadata
)Standard event types for SSE streaming:
from agent_runtime_core import EventType
EventType.ASSISTANT_MESSAGE # Agent response message
EventType.TOOL_CALL # Agent is calling a tool
EventType.TOOL_RESULT # Tool execution result
EventType.THINKING # Agent is thinking/processing
EventType.ERROR # Error occurred
EventType.STEP_STARTED # Multi-step: step started
EventType.STEP_COMPLETED # Multi-step: step completed
EventType.RUN_COMPLETED # Agent run completedDefine a tool with handler:
from agent_runtime_core import Tool, ToolRegistry
tool = Tool(
name="get_weather",
description="Get weather for a location",
parameters={
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name"}
},
"required": ["location"]
},
handler=my_handler_function, # async def my_handler(location: str) -> str
)
registry = ToolRegistry()
registry.register(tool)Fluent API for building tool schemas:
from agent_runtime_core import ToolSchemaBuilder
schema = (
ToolSchemaBuilder("search_products")
.description("Search the product catalog")
.param("query", "string", "Search query", required=True)
.param("category", "string", "Category filter", enum=["electronics", "clothing"])
.param("limit", "integer", "Max results", default=10)
.param("filters", "object", "Additional filters")
.param("tags", "array", "Tags to filter by", items={"type": "string"})
.build()
)
# Convert to OpenAI format
openai_tools = [schema.to_openai_format()]from agent_runtime_core.llm import get_llm_client
# Get configured client
llm = get_llm_client()
# Or specify provider
llm = get_llm_client(provider="anthropic", model="claude-3-5-sonnet-20241022")
# Generate response
response = await llm.generate(
messages=[
{"role": "system", "content": "You are helpful."},
{"role": "user", "content": "Hello!"}
],
tools=openai_tools, # Optional: for tool calling
temperature=0.7,
)
# Response structure
response.message # {"role": "assistant", "content": "..."}
response.tool_calls # List of tool calls (if any)
response.usage # Token usage infofrom agent_runtime_core.rag import chunk_text, ChunkingConfig, TextChunk
config = ChunkingConfig(
chunk_size=500, # Target chunk size in characters
chunk_overlap=50, # Overlap between chunks
min_chunk_size=100, # Minimum chunk size
)
chunks: list[TextChunk] = chunk_text(
text="Your document content...",
config=config,
metadata={"source": "manual.pdf"},
)from agent_runtime_core.rag import KnowledgeIndexer
from agent_runtime_core.vectorstore import get_vector_store, get_embedding_client
indexer = KnowledgeIndexer(
vector_store=get_vector_store("sqlite_vec", path="./vectors.db"),
embedding_client=get_embedding_client("openai"),
)
result = await indexer.index_text(
text="Document content...",
source_id="doc-123",
metadata={"name": "User Manual"},
)
# result.status, result.chunks_indexed, result.errorfrom agent_runtime_core.rag import KnowledgeRetriever, RetrievalConfig
retriever = KnowledgeRetriever(
vector_store=vector_store,
embedding_client=embedding_client,
default_config=RetrievalConfig(top_k=5, similarity_threshold=0.7),
)
results = await retriever.retrieve(
query="How do I reset my password?",
top_k=5,
similarity_threshold=0.7,
filter={"category": "support"},
)
# Format for prompt inclusion
formatted = retriever.format_results(results)from agent_runtime_core.vectorstore import get_vector_store
# SQLite with sqlite-vec (good for development)
store = get_vector_store("sqlite_vec", path="./vectors.db")
# PostgreSQL with pgvector (production)
store = get_vector_store("pgvector", connection_string="postgresql://...")
# Operations
await store.add(id="chunk-1", vector=[0.1, 0.2, ...], content="...", metadata={})
await store.add_batch(items=[...])
results = await store.search(query_vector=[...], limit=10, filter={"source_id": "doc-1"})
await store.delete(id="chunk-1")
await store.delete_by_filter({"source_id": "doc-1"})Extended context with Django features:
from django_agent_runtime.runtime.context import DjangoRunContext
# Available in your agent's run() method
ctx.user # Django User object (if authenticated)
ctx.request # Original HTTP request
ctx.conversation # AgentConversation model instancefrom django_agent_runtime.models import (
AgentRun, # Individual agent execution
AgentConversation, # Conversation thread
AgentEvent, # SSE events
StepCheckpoint, # Multi-step checkpoints
StepEvent, # Step execution events
)# Start agent workers
python manage.py runagent --processes 4 --concurrency 20
# Options:
# --processes N Number of worker processes
# --concurrency N Concurrent tasks per process
# --queue NAME Queue name to processStack: agent_runtime_core + django_agent_runtime + agent-frontend
- Basic conversational agent
- No state management needed
- Quick to deploy
Stack: agent_runtime_core (ToolCallingAgent) + django_agent_runtime + agent-frontend
- Agent with tools for actions (API calls, database queries, etc.)
- Automatic tool-calling loop
- State via Django checkpoints
Stack: agent_runtime_core + django_agent_runtime (with DjangoStepExecutor)
- Multi-step operations with checkpointing
- Resume capability after interruptions
- Progress tracking and event logging
Stack: agent_runtime_core + your framework + django_agent_runtime
- Use LangGraph, CrewAI, OpenAI Agents, etc.
- Leverage core abstractions and Django deployment
- Full flexibility
# LLM Provider
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
# Django
DATABASE_URL=postgres://...
REDIS_URL=redis://...
DEBUG=True
# Agent Runtime
DJANGO_AGENT_RUNTIME_DEBUG=1 # Enable debug mode-
Core Level (
agent_runtime_core)- LLM provider and model selection
- Queue and event bus backends
- Tracing configuration
- Debug mode (exception handling)
-
Django Level (
django_agent_runtime)- Database settings
- API authentication
- Worker configuration
- Event visibility
-
Frontend Level (
agent-frontend)- Backend URL
- Authentication strategy
- UI customization
| Feature | This Stack | LangChain + LangServe | OpenAI Assistants API | Custom Build |
|---|---|---|---|---|
| Framework Agnostic | โ | โ (LangChain only) | โ (OpenAI only) | โ |
| Model Agnostic | โ | โ | โ | โ |
| Self-Hosted | โ | โ | โ | โ |
| Production Queue | โ PostgreSQL | โ | โ | ๐จ Build it |
| Real-Time Streaming | โ SSE | โ | โ | ๐จ Build it |
| State Management | โ Built-in | โ | โ | ๐จ Build it |
| Frontend Widget | โ Included | โ | โ | ๐จ Build it |
| Django Integration | โ Native | ๐จ Custom | ๐จ Custom | ๐จ Build it |
| Tool Calling Loop | โ Built-in | โ | โ | ๐จ Build it |
| Zero Dependencies (Core) | โ | โ | N/A | Depends |
Each package includes comprehensive tests. See individual package repositories for testing instructions.
Each package has its own repository with detailed documentation:
Each package is published independently:
- PyPI:
agent-runtime-core,django-agent-runtime - npm:
@makemore/agent-frontend
- Additional LLM providers (Gemini, Cohere)
- Vector store integrations
- Enhanced tracing and observability
- WebSocket support
- GraphQL API
- Multi-tenancy support
- Advanced analytics dashboard
- Voice input support
- File upload handling
- Rich media messages
- Mobile app SDK
All packages are licensed under MIT License.
The codebase has been simplified:
Change: Removed agent_runtime_framework package. Useful utilities moved to agent_runtime_core.
Impact:
ToolSchemaBuildernow inagent_runtime_core.toolsToolCallingAgentin core provides tool-calling looprun_agentic_loopfunction for custom implementations- Simpler dependency chain: core โ django
Change: django_agent_runtime.runtime.registry uses agent_runtime_core.registry as its foundation.
Impact:
- Core registry supports factory functions and class registration
- Django's registry adds autodiscovery features on top
- Single source of truth for runtime registration
Change: Portable RAG implementation in agent_runtime_core.rag.
Impact:
chunk_text,ChunkingConfig,TextChunkfor text chunkingKnowledgeIndexer,KnowledgeRetrieverfor RAG workflows- Works standalone or with Django integration
Built with โค๏ธ for creating amazing conversational AI experiences.
This ecosystem provides a complete, production-ready solution for building AI agent systems:
- Modularity: Use only what you need - from core abstractions to full-stack deployment
- Framework Agnostic: Works with any agent framework (LangGraph, CrewAI, OpenAI, custom)
- Model Agnostic: Support for OpenAI, Anthropic, and any LiteLLM-compatible provider
- Production Ready: Battle-tested queue system, worker management, and real-time streaming
- Developer Friendly: Clear boundaries, comprehensive docs, and extensive examples
- Zero Lock-in: Each layer can be replaced or extended independently
| Scenario | Recommended Stack |
|---|---|
| Simple chatbot | agent_runtime_core + django_agent_runtime + agent-frontend |
| Tool-calling agent | Use ToolCallingAgent from agent_runtime_core |
| Long-running tasks | Use DjangoStepExecutor from django_agent_runtime |
| Custom framework | agent_runtime_core + your framework + django_agent_runtime |
| Standalone Python | agent_runtime_core only |
| Frontend only | agent-frontend with any backend |
- Issues: Open issues in the respective package repositories
- Discussions: Use GitHub Discussions for questions and ideas
- Examples: Check the
examples/directory in each package - Tests: Review test files for usage patterns
| Package | Python | Django | Node.js |
|---|---|---|---|
| agent_runtime_core | โฅ3.11 | N/A | N/A |
| django_agent_runtime | โฅ3.10 | โฅ4.2 | N/A |
| agent-frontend | N/A | N/A | โฅ12.0 |