The agents service is a single Bun process with a SQLite file and a data directory. It runs three ways: as a desktop subprocess, as a Docker container, or straight from source.
Configuration
Every setting is an environment variable with a matching CLI flag (agents/src/config.ts:93-114). An unknown or empty flag is a startup error rather than a silent default.
Variable | Default | Meaning |
|---|---|---|
|
| Bind hostname |
|
| HTTP port (dev shell uses |
|
| SQLite database |
|
| Per-agent state directories |
|
| The only server |
| falls back to HM URL | Direct |
|
| Trigger monitor interval |
|
| Activity feed page size |
|
| Pages per poll |
| unset | Enables |
| unset | Crawl4AI, for browser-render escalation |
| unset | Required by Crawl4AI ≥ 0.9 |
|
| Empty / |
|
| Sandbox image |
|
| TypeScript image; empty withholds the |
|
| vCPUs per sandbox |
|
| Guest memory |
|
| Default timeout (a call may ask up to 300) |
| on |
|
|
| Sandbox resolvers |
| off | Offers provider OAuth sign-in |
|
| Exactly |
Desktop-side variables control discovery, not the server: SEED_NO_AGENTS_SPAWN (never spawn, attach only) and SEED_AGENTS_SERVER_URL (attach here). See The Desktop Surface.
Deployment shapes
Desktop subprocess. The packaged app ships the server as a compiled binary and points it at the app's own daemon for both hypermedia and IPFS. microsandbox is staged beside the executable because its native pieces cannot be bundled; on macOS the binary needs the com.apple.security.hypervisor entitlement or sandbox creation fails.
Docker. seedhypermedia/agents:latest (release tags) and :dev (pushes to main touching agents/**). Production runs both behind Caddy on agentic.seed.hyper.media, with Watchtower polling every five minutes for new images.
> Known gap: the Dockerfile's final stage copies only package.json and dist/ — no node_modules — so microsandbox is not staged and code execution does not work in container images. This is tracked on the roadmap as an infrastructure change, not a code fix.
From source. cd agents && bun run dev, which the repo's ./dev up already does on port 3051.
Diagnostics
GET /agents is a built-in inspector: uptime, WebSocket connections, every agent, triggers grouped by agent with firing counts and last error, activity watermarks, sessions and their event counts. It refreshes every two seconds. It is also unauthenticated and exposes account ids, session titles, and event payloads — see Security. GET /agents/api/status and GET /agents/api/session?id=… are its JSON equivalents.
Logs are prefixed by subsystem, which makes grepping a live server tractable: [Agents Activity], [Agents Trigger], [agents/runs], [agents/runtime], [agents/workflow], [agents/ws], [agents/ui]. They carry ids, counts, statuses, sizes and timings — never secrets or full session content.
When something is wrong
From agents/docs/troubleshooting.md, the failures that actually recur:
A session stuck in streaming — check ListRuns. The truth is the run's status and wait reason (children, timer, event, budget-pause); StopSession or CancelRun resolves it.
Children ran but the parent never resumed — delegate {await: false} is detached by design. If it was awaited, look for unmetObligations: [{kind: 'typed-result'}] (Obligations).
call returned a tool contract — that is touch-expand working, not a failure. The retry executes.
A user action the agent can't see — InvokeSessionTool returns 409 while a run is live.
A script child misbehaving — read GetRunJournal. fuel-exhausted means more than two seconds of compute between awaits; journal-cap means the run exceeded 5,000 entries or 8 MiB and wants continueAsNew.
Server pinned at 100% CPU — Bun is single-threaded; something is in a busy loop. A past instance was an infinite loop in markdown parsing on an indented heading.
Schema mismatch at boot — the server refuses to start and says so; delete agents/data/agents.sqlite* and restart (Persistence).
Related
Testing — the gates before a deploy
Do you like what you are reading? Subscribe to receive updates.
Unsubscribe anytime