Norns Agent
Core AI agent backend providing agentic capabilities with long-term memory.
Overview
Norns Agent is a Python/FastAPI service that implements the core agent logic, including the Raven Model memory system.
| Property | Value |
|---|---|
| Container | norns-agent |
| URL | norns-pm.ravenhelm.dev |
| Port | 8000 (internal: 3901) |
| Config | ~/ravenhelm/docs/AI-ML-Platform/norns-agent/ |
| Source | ~/ravenhelm/docs/AI-ML-Platform/norns-agent/agent/ |
Architecture
┌─────────────────────────────────────────────────────────────┐
│ NORNS AGENT │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Huginn │───▶│ Context │───▶│ Muninn │ │
│ │ (State/Redis)│ │ (Identity) │ │ (Memory) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │
│ └───────────────────┼───────────────────┘ │
│ ▼ │
│ ┌──────────────┐ │
│ │ LangGraph │ │
│ │ Agent │ │
│ └──────────────┘ │
│ │ │
│ ┌───────────────────┼───────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Tools │ │ Claude │ │ Langfuse │ │
│ │ (HA, Cal...) │ │ API │ │ (Trace) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
See Norns Memory System for detailed memory architecture.
Communication Channels
Norns supports multiple communication channels, all routing through the same agent graph:
| Channel | Documentation | Description |
|---|---|---|
| Slack | Slack Integration | Direct messages and mentions |
| Voice | Norns Telephony | Phone calls via Twilio/LiveKit |
| Norns WhatsApp | WhatsApp messaging via Twilio |
All channels share:
- Same LangGraph agent graph
- Same tool capabilities
- Same memory system (Muninn)
- Unified session management
Capabilities
| Tool | Description |
|---|---|
task_manager | CRUD operations on tasks |
project_manager | Project management |
calendar | Google Calendar integration |
home_assistant | Smart home control |
grocy | Inventory management |
observability | Query Grafana/Loki/Prometheus |
slack | Post messages to Slack |
memory | Recall and search past interactions |
phone_call | Make outbound phone calls |
sms | Send SMS messages via Twilio |
Memory System
The agent implements the Raven Model - a three-plane cognitive architecture:
| Plane | Name | Purpose |
|---|---|---|
| State | Huginn | Real-time session state (Redis) |
| Identity | Context | User identity and permissions |
| Memory | Muninn | Long-term episodic and semantic memory |
Key Features:
- Vector embeddings via Ollama (nomic-embed-text)
- Semantic search across past interactions
- Automatic pattern extraction and learning
- Knowledge entity graph
See Norns Memory System for complete documentation.
API Endpoints
Core API
| Endpoint | Method | Description |
|---|---|---|
/health | GET | Health check |
/api/chat | POST | Send chat message |
/api/tasks | GET/POST | Task management |
/api/projects | GET/POST | Project management |
/api/memory/recall | POST | Search memories |
Channel Webhooks
| Endpoint | Method | Description |
|---|---|---|
/slack/events | POST | Slack event webhook |
/telephony/webhook | POST | Twilio voice webhook |
/whatsapp/webhook | POST | WhatsApp inbound messages |
/whatsapp/status | POST | WhatsApp delivery status |
WhatsApp API
| Endpoint | Method | Description |
|---|---|---|
/api/whatsapp/send | POST | Send proactive template message |
/api/whatsapp/templates | GET | List configured templates |
/api/whatsapp/session/{phone} | GET | Check session window status |
Quick Commands
# View logs
docker logs -f norns-agent
# Restart
docker restart norns-agent
# Shell access
docker exec -it norns-agent bash
# Test health
curl https://norns-pm.ravenhelm.dev/health
# Check memory stats
docker exec -i postgres psql -U ravenhelm -d ravenmaskos -c \
"SELECT COUNT(*) as memories FROM episodic_memories;"
Configuration
Environment Variables
environment:
# Database
- DB_HOST=postgres
- DB_PORT=5432
- DB_NAME=ravenmaskos
- DB_USER=ravenhelm
- DB_PASSWORD=${POSTGRES_PASSWORD}
# Redis
- REDIS_HOST=redis
- REDIS_PORT=6379
- REDIS_PASSWORD=${REDIS_PASSWORD}
# LLM Providers
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- OPENAI_API_KEY=${OPENAI_API_KEY}
- OLLAMA_URL=http://ollama:11434
# Embeddings
- EMBEDDING_PROVIDER=auto
- OLLAMA_EMBED_MODEL=nomic-embed-text
# Langfuse
- LANGFUSE_HOST=http://langfuse-web:3000
- LANGFUSE_PUBLIC_KEY=${LANGFUSE_PUBLIC_KEY}
- LANGFUSE_SECRET_KEY=${LANGFUSE_SECRET_KEY}
# Slack
- SLACK_BOT_TOKEN=${SLACK_BOT_TOKEN}
# Twilio (Voice + WhatsApp)
- TWILIO_ACCOUNT_SID=${TWILIO_ACCOUNT_SID}
- TWILIO_AUTH_TOKEN=${TWILIO_AUTH_TOKEN}
- TWILIO_WHATSAPP_NUMBER=${TWILIO_WHATSAPP_NUMBER}
# WhatsApp Templates
- WA_TEMPLATE_TASK_REMINDER=${WA_TEMPLATE_TASK_REMINDER:-}
- WA_TEMPLATE_DAILY_BRIEFING=${WA_TEMPLATE_DAILY_BRIEFING:-}
- WA_TEMPLATE_CALENDAR_REMINDER=${WA_TEMPLATE_CALENDAR_REMINDER:-}
- WA_TEMPLATE_TASK_COMPLETE=${WA_TEMPLATE_TASK_COMPLETE:-}
- WA_TEMPLATE_WEEKLY_REVIEW=${WA_TEMPLATE_WEEKLY_REVIEW:-}
# Integrations
- HOMEASSISTANT_URL=http://homeassistant:8123
- HOMEASSISTANT_TOKEN=${HOMEASSISTANT_TOKEN}
Slack Integration
Norns responds to messages in Slack via "The Norns" bot:
- User mentions @The Norns in Slack
- Slack sends event to
/slack/events - Agent processes request with full context
- Memory is recorded for future recall
- Response posted back to thread
WhatsApp Integration
Norns responds to WhatsApp messages via Twilio:
- User sends WhatsApp message
- Twilio sends webhook to
/whatsapp/webhook - Agent processes request with full context
- Memory is recorded for future recall
- Response sent back via Twilio API
Key features:
- 24-hour session window tracking
- Proactive templates for scheduled messages
- Rich messaging support (buttons, lists)
See Norns WhatsApp Channel for full documentation.
Troubleshooting
Issue: Agent Not Responding
Symptoms: No response to chat or Slack messages
Diagnosis:
docker logs norns-agent | tail -50
curl https://norns-pm.ravenhelm.dev/health
Solutions:
- Check API keys are valid
- Verify database connectivity
- Check Langfuse is reachable
Issue: Tool Execution Failed
Symptoms: Agent responds but tool fails
Diagnosis:
# Check Langfuse for trace details
docker logs norns-agent 2>&1 | grep -A 10 "Error"
Solutions:
- Verify integration credentials
- Check target service is running
- Review Langfuse traces for details
Issue: Memory Not Working
See Norns Memory System Troubleshooting
Issue: WhatsApp Not Working
Social Domain
The Social domain handles all communication tasks including Slack, phone calls, and SMS.
Workers
| Worker | Description | Requires |
|---|---|---|
SlackMessagingWorker | Send Slack messages and DMs | SLACK_BOT_TOKEN |
PhoneCallWorker | Make outbound calls | TELEPHONY_URL, NORNS_API_KEY |
SMSWorker | Send SMS via Twilio | TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_FROM_NUMBER |
Routing
The classifier routes messages to the SOCIAL domain when they involve:
- Sending messages (Slack, SMS)
- Making phone calls
- Communication with people
Examples:
- "Send John a message on Slack" → SOCIAL → SlackMessagingWorker
- "Call Sarah" → SOCIAL → PhoneCallWorker
- "Text mom that I'm on my way" → SOCIAL → SMSWorker
SMS Worker
Sends SMS via Twilio REST API:
# Environment variables
TWILIO_ACCOUNT_SID=<account_sid>
TWILIO_AUTH_TOKEN=<auth_token>
TWILIO_FROM_NUMBER=+17372143330
# Example usage
await sms_worker.execute(
state=agent_state,
action="text mom I'll be home soon",
slack_user_id="U123456"
)
Phone number resolution:
- Checks user's
phone_numberstable for contact names - Falls back to E.164 parsing for explicit numbers
- Rejects unknown contacts for safety
Multi-Task Execution
Norns supports compound requests that involve multiple independent tasks.
How It Works
- Classification: The classifier identifies compound requests and creates
action_items - Parallel Execution: Tasks are dispatched concurrently using
asyncio.as_completed() - Streaming: Each task streams its own progress independently
- Aggregation: Results are combined for the final response
Example
Request: "Add eggs to the shopping list, check my calendar for tomorrow, and send John a message"
Decomposition:
{
"requires_iteration": true,
"action_items": [
{"action": "add eggs to shopping list", "domain": "task"},
{"action": "check calendar for tomorrow", "domain": "calendar"},
{"action": "send John a message", "domain": "social"}
]
}
Execution: All three tasks execute in parallel, streaming their progress as they complete.
Routing Rules
The classifier determines:
requires_iteration: false→ Single domain handles the requestrequires_iteration: true→ Multiple domains execute in parallel
Compound request patterns:
- "X and Y and Z"
- "Do A, then B"
- "First X, also Y"