Agent Loop

The AgentLoop is the central orchestrator in PocketPaw. It consumes messages from the bus, builds context, delegates to the agent backend, and streams responses back.

Responsibilities

The AgentLoop handles:

  1. Message consumption — Subscribes to InboundMessage events from the bus
  2. Security checks — Runs Guardian AI and injection scanner on incoming messages
  3. Context building — Assembles system prompt with identity, memory, and state
  4. Backend delegation — Routes to the configured agent backend via AgentRouter
  5. Response streaming — Publishes OutboundMessage chunks back to the bus
  6. Memory updates — Saves conversation history and triggers Mem0 auto-learn
  7. System events — Emits tool activity events for the web dashboard
  8. Inbox updates — Publishes cross-channel inbox events

Processing Flow

# Simplified AgentLoop flow
async def handle_message(self, message: InboundMessage):
# 1. Security check
threat = await self.guardian.check(message.content)
if threat.level >= ThreatLevel.HIGH:
await self.bus.publish(OutboundMessage(
content="Message blocked by safety check",
...
))
return
# 2. Injection scan
if await self.scanner.scan(message.content):
return # Block injected messages
# 3. Build context
context = await self.context_builder.build(
session_id=message.session_id,
user_query=message.content,
)
# 4. Delegate to backend
async for chunk in self.router.process(context, message.content):
if chunk["type"] == "message":
await self.bus.publish(OutboundMessage(
content=chunk["content"],
is_stream_chunk=True,
...
))
elif chunk["type"] == "tool_use":
await self.bus.publish(SystemEvent(
event_type="tool_start",
data=chunk["metadata"],
))
# 5. Save to memory
await self.memory.save(message.session_id, message.content, response)
# 6. Trigger Mem0 auto-learn (background task)
if settings.mem0_auto_learn:
asyncio.create_task(self.mem0.learn(message.content, response))

Agent Router

The AgentRouter selects and delegates to one of three backends:

BackendSetting ValueBest For
Claude Agent SDKclaude_agent_sdkCoding, complex reasoning, built-in tools
PocketPaw Nativepocketpaw_nativeBalanced capability and control
Open Interpreteropen_interpreterLocal models via Ollama

The router lazily imports the selected backend to avoid loading unused dependencies.

Response Standardization

All backends yield standardized dictionaries:

{
"type": "message", # message, tool_use, tool_result, error, done
"content": "...", # Text content
"metadata": { # Backend-specific metadata
"tool_name": "...",
"tool_input": {...},
}
}

This ensures consistent behavior regardless of which backend is active.

Concurrency

The AgentLoop processes one message per session at a time. If a new message arrives while processing, it’s queued. Different sessions can be processed concurrently.