Architecture
Architecture
How kern's processes fit together.
Overview
Browser ──→ kern web (:9000) ──→ agent A (:random)
├─→ agent B (:random)
└─→ agent C (:random)
TUI ──────────────────────────→ agent A (:random)
Telegram ←────────────────────→ agent A (long poll)
Slack ←───────────────────────→ agent A (socket mode)
Each agent is a separate process. The web server is a separate process. They communicate over HTTP on localhost.
Agent process
kern start launches an agent as a background daemon. Each agent process:
- Binds an HTTP server to
127.0.0.1on a random port (OS-assigned) - Registers its PID, port, and auth token in
~/.kern/agents.json - Connects to Telegram (long polling) and/or Slack (socket mode) if tokens are configured
- Runs the message queue, tool executor, and model calls
- Serves SSE for real-time streaming to connected clients (TUI, web UI)
The agent never binds to 0.0.0.0 — it's only reachable from localhost. All external access goes through the web proxy.
Agent HTTP endpoints
These are internal — the web proxy forwards to them, TUI connects directly.
| Endpoint | Method | Purpose |
|---|---|---|
/events |
GET | SSE stream (messages, tool calls, status) |
/message |
POST | Send a message to the agent |
/status |
GET | Agent status, model, uptime, token counts |
/history |
GET | Message history with pagination |
/health |
GET | Liveness check |
/segments |
GET | Semantic segment data |
/segments/rebuild |
POST | Trigger segment re-indexing |
/context/system |
GET | Full composed system prompt |
/context/segments |
GET | Segments currently in context |
/sessions |
GET | Session list with current session ID |
/recall/stats |
GET | Recall index stats |
Auth
Each agent generates a random token on first start, stored in .kern/.env as KERN_AGENT_TOKEN. Every request must include Authorization: Bearer <token>. The TUI reads the token from the agent's .env file. The web proxy reads it from the registry.
Web server
kern web start launches a separate HTTP server (default port 9000, configurable in ~/.kern/config.json).
It serves two things:
- Static files — the web UI (HTML, CSS, JS)
- Agent proxy — forwards
/api/agents/:name/*to the correct agent process
Proxy flow
Browser → GET /api/agents/vega/status
→ kern web reads ~/.kern/agents.json
→ finds vega: { port: 34521, token: "abc..." }
→ forwards to 127.0.0.1:34521/status with Authorization header
→ streams response back to browser
The browser never knows agent ports or tokens. It authenticates once with KERN_WEB_TOKEN (auto-generated, stored in ~/.kern/.env), and the proxy handles the rest.
Web auth
A single token (KERN_WEB_TOKEN) protects the web server. It's generated on first kern web start and printed as part of the URL:
http://100.115.98.30:9000?token=abc123...
The browser stores this token and sends it with every request. No per-agent auth from the browser side — the proxy injects agent tokens internally.
Registry
~/.kern/agents.json is the coordination point. Every agent registers itself on start:
[
{
"name": "vega",
"path": "/root/vega",
"pid": 12345,
"port": 34521,
"token": "kern_...",
"addedAt": "2026-03-26T10:00:00Z"
}
]
The web server and TUI read this file to discover agents. kern list reads it to show status. PIDs are checked with kill -0 to detect stale entries.
TUI
kern tui [name] connects directly to an agent's HTTP server — no web proxy involved. It reads the agent's port and token from the registry, opens an SSE connection for streaming, and sends messages via POST. It's a direct localhost connection.
Telegram & Slack
These run inside the agent process itself — not separate services.
- Telegram: grammY bot with long polling. No incoming port needed.
- Slack: Bolt with Socket Mode. No incoming port needed.
Both inject messages into the same queue as TUI and web. The agent doesn't know or care which interface a message came from — it sees metadata tags like [via telegram, user: oguz].
Service management
kern install creates systemd user services for agents and the web server. This gives you:
- Auto-restart on crash
- Start on boot (with lingering enabled)
- Standard
systemctl --usermanagement
kern install vega # install agent as systemd service
kern install --web # install web server as systemd service
kern uninstall vega # remove service
Without kern install, agents run as plain daemons managed by PID files.
File layout
~/.kern/
agents.json # agent registry (discovery, PIDs, ports, tokens)
config.json # global config (web port, host)
.env # KERN_WEB_TOKEN
web.pid # web server PID
~/my-agent/
.kern/
config.json # agent config (model, provider, toolScope)
.env # API keys, bot tokens, KERN_AGENT_TOKEN
sessions/ # conversation JSONL
recall.db # memory database (embeddings, segments, summaries)
logs/ # structured logs
AGENTS.md # agent behavior
IDENTITY.md # agent identity
KNOWLEDGE.md # knowledge index
USERS.md # paired users
knowledge/ # mutable state files
notes/ # daily logs
Port summary
| Process | Binds to | Port | Accessible from |
|---|---|---|---|
| Agent | 127.0.0.1 | random | localhost only |
| Web server | 0.0.0.0 (configurable) | 9000 (configurable) | LAN / Tailscale |
| Telegram | outbound only | — | — |
| Slack | outbound only | — | — |