Skip to content

makemore/agent-libraries

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

3 Commits
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Agent Libraries Ecosystem

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.

๐Ÿ“– Table of Contents

  1. Step-by-Step Django Setup Guide - Start here for new projects
  2. Package Overview - What each package does
  3. Architecture & Boundaries - How they fit together
  4. API Reference - Key classes and functions
  5. Use Cases & Patterns - Common implementation patterns

๐Ÿ› ๏ธ Step-by-Step Django Setup Guide

This guide walks through setting up a complete AI agent system in an existing Django project.

Prerequisites

  • Python 3.11+
  • Django 4.2+
  • PostgreSQL (recommended) or SQLite
  • OpenAI API key (or Anthropic)

Step 1: Install Packages

# 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]

Step 2: Configure Django Settings

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,
}

Step 3: Add URL Routes

In your urls.py:

from django.urls import path, include

urlpatterns = [
    # ... your existing urls ...
    path('api/agents/', include('django_agent_runtime.urls')),
]

Step 4: Run Migrations

python manage.py migrate

This creates the following tables:

  • agent_run - Stores agent execution runs
  • agent_conversation - Stores conversation history
  • agent_event - Stores events for SSE streaming
  • step_checkpoint - Stores checkpoints for long-running tasks
  • step_event - Stores step execution events

Step 5: Create Your First Agent

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())

Step 6: Start the Services

You need two processes running:

Terminal 1 - Django Server:

python manage.py runserver

Terminal 2 - Agent Workers:

# Start workers to process agent runs
python manage.py runagent --processes 2 --concurrency 10

Step 7: Test the API

# 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/

Step 8: Add Frontend Widget (Optional)

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>

๐Ÿ”ง Creating Tool-Calling Agents

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())

Using ToolSchemaBuilder (Fluent API)

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()

๐Ÿ“š Adding RAG (Retrieval Augmented Generation)

For agents that need to search knowledge bases:

Step 1: Set Up Vector Store

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")

Step 2: Index Documents

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")

Step 3: Retrieve in Your Agent

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]
        )

๐Ÿง  Cross-Conversation Memory

Enable agents to remember facts, preferences, and context across conversations.

Quick Start: Enable Memory on Any Agent

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
)

How It Works

  1. Before each run: Relevant memories are recalled and injected into the system prompt
  2. After each run: New facts are extracted from the conversation and stored
  3. Memories are scoped per user: Use user_id in context metadata

Using MemoryManager Directly

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 user

Memory Configuration Options

from 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
)

Using with_memory() Helper

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 configured

Django Integration

In 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 Overview

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

๐Ÿ—๏ธ Architecture & Boundaries

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                         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                                 โ”‚    โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ”— How They Work Together

Full Stack Flow

  1. User Interaction โ†’ agent-frontend (JavaScript widget in browser)
  2. HTTP Request โ†’ django_agent_runtime (REST API creates AgentRun)
  3. Queue Job โ†’ PostgreSQL queue stores the run
  4. Worker Picks Up โ†’ runagent worker process claims the job
  5. Agent Execution โ†’ Your agent (using ToolCallingAgent or custom AgentRuntime)
  6. Core Execution โ†’ agent_runtime_core handles LLM calls, tools, events
  7. Real-time Events โ†’ SSE stream back to agent-frontend
  8. UI Updates โ†’ Widget displays messages in real-time

Dependency Chain

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)

๐Ÿ“‹ Package Boundaries

agent_runtime_core

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

django_agent_runtime

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 (runagent command)
  • โœ… DjangoStepExecutor with database checkpointing
  • โœ… DjangoRunContext for ORM-backed context
  • โœ… StepCheckpoint & StepEvent models
  • โœ… Anonymous session support
  • โœ… Event visibility system
  • โœ… Debug/production mode configuration
  • โŒ No frontend code

agent-frontend

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

๐Ÿ“– API Reference

Core Interfaces (agent_runtime_core)

AgentRuntime (Protocol)

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
        pass

RunContext (Protocol)

Provides 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."""

RunResult

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
)

EventType

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 completed

Tool System

Tool

Define 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)

ToolSchemaBuilder

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()]

LLM Clients

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 info

RAG Module

Chunking

from 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"},
)

Indexing

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.error

Retrieval

from 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)

Vector Stores

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"})

Django-Specific (django_agent_runtime)

DjangoRunContext

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 instance

Models

from django_agent_runtime.models import (
    AgentRun,           # Individual agent execution
    AgentConversation,  # Conversation thread
    AgentEvent,         # SSE events
    StepCheckpoint,     # Multi-step checkpoints
    StepEvent,          # Step execution events
)

Management Commands

# 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 process

๐ŸŽฏ Use Cases & Patterns

Pattern 1: Simple Chatbot

Stack: agent_runtime_core + django_agent_runtime + agent-frontend

  • Basic conversational agent
  • No state management needed
  • Quick to deploy

Pattern 2: Tool-Calling Agent

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

Pattern 3: Long-Running Tasks

Stack: agent_runtime_core + django_agent_runtime (with DjangoStepExecutor)

  • Multi-step operations with checkpointing
  • Resume capability after interruptions
  • Progress tracking and event logging

Pattern 4: Custom Framework

Stack: agent_runtime_core + your framework + django_agent_runtime

  • Use LangGraph, CrewAI, OpenAI Agents, etc.
  • Leverage core abstractions and Django deployment
  • Full flexibility

๐Ÿ”ง Configuration & Environment

Environment Variables

# 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

Configuration Hierarchy

  1. Core Level (agent_runtime_core)

    • LLM provider and model selection
    • Queue and event bus backends
    • Tracing configuration
    • Debug mode (exception handling)
  2. Django Level (django_agent_runtime)

    • Database settings
    • API authentication
    • Worker configuration
    • Event visibility
  3. Frontend Level (agent-frontend)

    • Backend URL
    • Authentication strategy
    • UI customization

๐Ÿ“Š Comparison with Other Solutions

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

๐Ÿงช Testing

Each package includes comprehensive tests. See individual package repositories for testing instructions.

๐Ÿ“š Documentation Links

Each package has its own repository with detailed documentation:

๐Ÿ“ฆ Publishing

Each package is published independently:

  • PyPI: agent-runtime-core, django-agent-runtime
  • npm: @makemore/agent-frontend

๐Ÿ”ฎ Roadmap

agent_runtime_core

  • Additional LLM providers (Gemini, Cohere)
  • Vector store integrations
  • Enhanced tracing and observability

django_agent_runtime

  • WebSocket support
  • GraphQL API
  • Multi-tenancy support
  • Advanced analytics dashboard

agent-frontend

  • Voice input support
  • File upload handling
  • Rich media messages
  • Mobile app SDK

๐Ÿ“„ License

All packages are licensed under MIT License.

๐Ÿ”„ Recent Refactoring (v0.7.0)

The codebase has been simplified:

1. โœ… Simplified Architecture

Change: Removed agent_runtime_framework package. Useful utilities moved to agent_runtime_core.

Impact:

  • ToolSchemaBuilder now in agent_runtime_core.tools
  • ToolCallingAgent in core provides tool-calling loop
  • run_agentic_loop function for custom implementations
  • Simpler dependency chain: core โ†’ django

2. โœ… Registry Consolidation

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

3. โœ… RAG Module

Change: Portable RAG implementation in agent_runtime_core.rag.

Impact:

  • chunk_text, ChunkingConfig, TextChunk for text chunking
  • KnowledgeIndexer, KnowledgeRetriever for RAG workflows
  • Works standalone or with Django integration

๐Ÿ™ Acknowledgments

Built with โค๏ธ for creating amazing conversational AI experiences.


๐Ÿ“ Summary

This ecosystem provides a complete, production-ready solution for building AI agent systems:

Key Strengths

  1. Modularity: Use only what you need - from core abstractions to full-stack deployment
  2. Framework Agnostic: Works with any agent framework (LangGraph, CrewAI, OpenAI, custom)
  3. Model Agnostic: Support for OpenAI, Anthropic, and any LiteLLM-compatible provider
  4. Production Ready: Battle-tested queue system, worker management, and real-time streaming
  5. Developer Friendly: Clear boundaries, comprehensive docs, and extensive examples
  6. Zero Lock-in: Each layer can be replaced or extended independently

When to Use Each Package

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

Getting Help

  • 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

Version Compatibility

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

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors