Skip to content

Multi-Agent System#

lit-mux supports deploying multiple AI agents with distinct configurations, roles, and capabilities. Agents can communicate with each other, operate autonomously via heartbeat, and be organized into hierarchies.

Agent Concepts#

What is an Agent?#

An agent is a configured AI entity with:

  • Identity: Unique ID, name, and role
  • Backend: Which LLM to use (Claude, Gemini, Ollama, etc.)
  • Tools: Which MCP servers are available
  • Behavior: System prompt, temperature, working directory
  • Sessions: Conversations belong to agents

Agent vs Session#

Concept Purpose Lifecycle
Agent Configuration template Long-lived, persisted
Session Conversation instance Created per conversation

Think of agents as "personalities" and sessions as "conversations with that personality."

Creating Agents#

Via API#

import httpx

agent = httpx.post("http://localhost:8000/agents", json={
    "id": "code-reviewer",
    "name": "Code Reviewer",
    "backend": "claude-cli",
    "model": "claude-sonnet-4-20250514",
    "role": "Senior Engineer",
    "system_prompt": "You are a senior engineer reviewing code...",
    "temperature": 0.3,
    "working_dir": "/home/projects",
    "mcp_servers": ["git", "filesystem"]
}).json()

Via Configuration File#

Agents can be defined in JSON files at ~/.config/lit-mux/agents/:

{
    "id": "code-reviewer",
    "name": "Code Reviewer",
    "backend": "claude-cli",
    "model": "claude-sonnet-4-20250514",
    "role": "Senior Engineer",
    "system_prompt": "You are a senior engineer reviewing code for quality, security, and best practices.",
    "temperature": 0.3,
    "working_dir": "/home/projects",
    "mcp_servers": ["git", "filesystem"],
    "metadata": {
        "department": "engineering",
        "specialty": "code-review"
    }
}

Agent Configuration#

Core Fields#

Field Type Description
id string Unique identifier
name string Human-readable name
backend string LLM backend (claude-cli, gemini, ollama, etc.)
model string Model ID for the backend
role string Agent's role/title
system_prompt string Instructions for the agent
temperature float Creativity (0.0-1.0)
max_tokens int Maximum response length
working_dir string Filesystem root for tools

MCP Configuration#

{
    "mcp_servers": ["git", "jira", "filesystem"],
    "mcp_server_overrides": {
        "jira": {
            "project_key": "PROJ"
        },
        "filesystem": {
            "allowed_directories": ["/home/projects"]
        }
    }
}

Heartbeat Configuration#

For autonomous agents that wake periodically:

{
    "heartbeat_enabled": true,
    "heartbeat_interval": 30,
    "heartbeat_prompt": "Check for new tasks and update status...",
    "heartbeat_stimuli": [
        {
            "type": "jira_tickets",
            "project": "PROJ",
            "jql": "assignee = currentUser() AND status = 'In Progress'"
        },
        {
            "type": "git_commits",
            "repo": "/home/projects/main"
        }
    ]
}

Agent-to-Agent Messaging#

Agents can send messages to each other via typed message queues.

Sending Messages#

# From one agent to another
response = httpx.post("http://localhost:8000/messages/agent", json={
    "from_agent_id": "project-manager",
    "to_agent_id": "code-reviewer",
    "content": "Please review PR #123",
    "priority": "HIGH"
})
message_id = response.json()["id"]

Message Priority#

Priority Use Case
LOW Background tasks, FYI
NORMAL Standard requests
HIGH Time-sensitive work
URGENT Immediate attention needed

Checking Message Status#

status = httpx.get(f"http://localhost:8000/messages/{message_id}").json()
# Returns: { "status": "delivered", "delivered_at": "..." }

MCP Tool for Messaging#

Agents can also send messages using the built-in MCP tool:

mcp__agent-messaging__send_agent_message(
    to_agent_id="code-reviewer",
    content="Please review PR #123",
    priority="HIGH"
)

Agent Hierarchy#

Agents can be organized into parent-child relationships:

{
    "id": "frontend-dev",
    "name": "Frontend Developer",
    "parent_id": "tech-lead",
    "organization_id": "engineering-team"
}

Use Cases#

  • Team Structure: Tech lead → developers
  • Specialization: General assistant → domain experts
  • Delegation: Manager agents that route to specialists

Organizations (Agent Groups)#

Group agents into organizations for multi-tenant deployments:

# Create organization
org = httpx.post("http://localhost:8000/organizations", json={
    "name": "Engineering Team",
    "metadata": {"department": "engineering"}
}).json()

# Create agent in organization
agent = httpx.post("http://localhost:8000/agents", json={
    "id": "eng-assistant",
    "name": "Engineering Assistant",
    "organization_id": org["id"],
    ...
}).json()

Heartbeat System#

The heartbeat system enables autonomous agent behavior. Agents wake periodically to:

  1. Check for stimuli (new data, events, messages)
  2. Process and respond to stimuli
  3. Return to sleep

Stimuli Types#

Stimulus Description
jira_tickets Check for Jira ticket updates
git_commits Monitor repository commits
inbox_messages Check message queue
mattermost_check Monitor chat channels

Heartbeat Flow#

┌─────────────┐
│   Sleep     │
└──────┬──────┘
       │ (interval elapsed)
┌─────────────┐
│ Wake Up     │
└──────┬──────┘
┌─────────────┐
│ Check       │
│ Stimuli     │
└──────┬──────┘
┌─────────────────┐
│ Stimuli Found?  │
└────┬───────┬────┘
     │ No    │ Yes
     │       ▼
     │  ┌─────────────┐
     │  │ Process     │
     │  │ Stimuli     │
     │  └──────┬──────┘
     │         │
     ▼         ▼
┌─────────────┐
│   Sleep     │
└─────────────┘

Heartbeat API#

# Check heartbeat status
status = httpx.get(f"http://localhost:8000/agents/{agent_id}/heartbeat/status").json()
# Returns: { "enabled": true, "last_wake": "...", "next_wake": "..." }

# WebSocket for real-time heartbeat events
ws = websocket.connect("ws://localhost:8000/ws/heartbeat")
while True:
    event = ws.recv()
    print(f"Heartbeat event: {event}")

Agent Sessions#

Each agent maintains its own sessions:

# Get sessions for an agent
sessions = httpx.get(f"http://localhost:8000/agents/{agent_id}/sessions").json()

# Search agent's sessions
sessions = httpx.get(
    f"http://localhost:8000/agents/{agent_id}/sessions?q=code review"
).json()

Session Types#

Session Purpose
primary_session_id Main conversation session
heartbeat_session_id Autonomous heartbeat session
processing_session_id Background task processing

Agent Status#

Track agent activity:

agent = httpx.get(f"http://localhost:8000/agents/{agent_id}").json()

print(agent["status"])  # idle, receiving, processing, sending, error, offline
print(agent["active_conversations"])
print(agent["messages_in_queue"])
print(agent["last_activity"])

Streaming to Agents#

Stream messages directly to an agent (creates/uses their primary session):

with httpx.stream("POST",
    f"http://localhost:8000/agents/{agent_id}/stream",
    json={"message": "Review this code..."}
) as response:
    for line in response.iter_lines():
        print(line)

Best Practices#

Agent Design#

  1. Single Responsibility: Each agent should have a focused role
  2. Clear System Prompts: Be explicit about agent behavior
  3. Appropriate Tools: Only enable MCP servers the agent needs
  4. Temperature Tuning: Lower for precise tasks, higher for creative

Multi-Agent Patterns#

  1. Hub and Spoke: Central coordinator routes to specialists
  2. Pipeline: Agents process in sequence (e.g., draft → review → publish)
  3. Peer Network: Agents collaborate as equals
  4. Hierarchical: Management layers with delegation

Performance#

  1. Session Reuse: Use existing sessions when possible
  2. Message Batching: Group related messages
  3. Heartbeat Tuning: Balance responsiveness vs. resource usage

Example: Code Review Team#

// tech-lead.json
{
    "id": "tech-lead",
    "name": "Tech Lead",
    "role": "Technical Lead",
    "system_prompt": "You coordinate code reviews and delegate to specialists.",
    "mcp_servers": ["git", "jira", "agent-messaging"]
}

// frontend-reviewer.json
{
    "id": "frontend-reviewer",
    "name": "Frontend Reviewer",
    "role": "Frontend Specialist",
    "parent_id": "tech-lead",
    "system_prompt": "You review frontend code for React best practices.",
    "mcp_servers": ["git", "filesystem"]
}

// backend-reviewer.json
{
    "id": "backend-reviewer",
    "name": "Backend Reviewer",
    "role": "Backend Specialist",
    "parent_id": "tech-lead",
    "system_prompt": "You review backend code for security and performance.",
    "mcp_servers": ["git", "filesystem"]
}

The tech lead receives review requests, analyzes the PR, and delegates to the appropriate specialist.