Skip to main content
The Agent Manager is the LLM brain of the server. It runs as a long-lived asyncio worker alongside the Communication Manager and Channel Manager. For every inbound text message it invokes a LangChain agent, maintains per-conversation memory, and pushes the reply back through the Communication Manager’s outbound queue to the originating channel.

Message flow

The Agent Manager processes one message at a time. Non-text messages (images, audio, etc.) are drained from the queue and silently dropped — the current worker is the only consumer of inbound_queue.
Agent Manager message processing flow

Conversation memory

Each conversation is isolated by a thread_id built from channel:sender_id. The agent uses a LangGraph InMemorySaver checkpointer shared across all conversations — the full message history for each thread is stored in memory and passed automatically on every invocation. This means the agent remembers context within a conversation across multiple exchanges, without you needing to resend history.
Memory is lost on server restart. For persistence across restarts, InMemorySaver can be replaced with SqliteSaver or PostgresSaver from LangGraph — this is planned for a future release.

Tools

The Agent Manager loads all registered Hiro League tools at startup via all_tools() and makes them available to the agent. The agent can invoke any of these tools as part of processing a message. Current tool categories available to the agent:
CategoryTools
Devicesdevice-add, device-list, device-revoke
Channelschannel-list, channel-install, channel-setup, channel-enable, channel-disable, channel-remove
Workspacesworkspace-list, workspace-create, workspace-remove, workspace-set-default, workspace-show
Serversetup, start, stop, status, teardown, uninstall
These are the same tools available through the CLI and HTTP Server. See Tools architecture for how the shared tool interface works.

Configuration

All agent configuration lives under <workspace>/agent/. Files are created with safe defaults on first run if absent.

<workspace>/agent/config.json

Controls which LLM provider and model the agent uses.
{
  "provider": "openai",
  "model": "gpt-4.1-mini",
  "temperature": 0.7,
  "max_tokens": 1024
}
FieldTypeDescription
providerstringLangChain provider identifier — e.g. openai, anthropic, ollama
modelstringModel name understood by the provider — e.g. gpt-4.1-mini, claude-sonnet-4-5
temperaturefloat 0–2Sampling temperature
max_tokensintMaximum tokens in the generated reply
The provider and model values are combined as "provider:model" and passed to langchain.chat_models.init_chat_model. To switch providers, install the corresponding LangChain package and update config.json:
# Anthropic
uv add langchain-anthropic

# Ollama (local)
uv add langchain-ollama
{
  "provider": "anthropic",
  "model": "claude-sonnet-4-5-20250929"
}

<workspace>/agent/system_prompt.md

A plain markdown file loaded verbatim as the agent’s system prompt. Edit it to change the agent’s persona, tone, or domain focus. The file is read once at server startup. Default content:
You are a helpful home assistant running on Hiro League.
Answer questions concisely and helpfully.

Lifecycle

AgentManager is constructed after CommunicationManager is set up, then added to asyncio.gather alongside the other server coroutines. The run() loop processes messages sequentially — one at a time — for simplicity. Concurrent processing per conversation can be added later without changing the CommunicationManager interface.
agent_manager = AgentManager(comm_manager, workspace_path)

await asyncio.gather(
    run_http_server(config, stop_event),
    channel_manager.run(),
    comm_manager.run(),
    agent_manager.run(),
)

See also