Introduction

OverviewArchitectureAgent Experience

The product

This repository

Structure

Usage

Other

Concepts

Agents and machines

Workspaces, users, the Agent record, the Machine that hosts a runtime, and how routing reads them

Not built yet. There is no Agent table and no Machine table, and no MCP server is running. packages/database still ships a single stub model inherited from the template this repository forked. Clerk authentication and organizations are wired up today; everything below the Workspace and User sections describes the intended shape, taken from spec/01-domain-model.md.

An Agent in this system is a record, not a process. It has an identity, a persona, capabilities, a home machine and a status. Nothing is executed here. The Agent record is what a remote Claude Code or Codex session authenticates as when it claims work.

Workspace

The tenant boundary, mapped to a Clerk organization. It holds settings, the default board columns, and policy flags such as requireApprovalForDestructiveTools.

Every row in the domain carries workspaceId. No cross-workspace read is possible, including for agent tokens. Slugs are unique per workspace, not globally.

User

A human, backed by Clerk. Roles are owner, admin, member and viewer. Users request tasks (requestedByUserId), answer blocking questions, and decide approvals.

Agent

FieldNotes
name, slug, avatarIdentity in the UI.
runtimeclaude-code, codex or custom.
personaMarkdown system prompt and operating instructions, injected into the remote session.
capabilities[]Free-form tags such as rust, next.js, browser, deploy. Used for routing.
toolAllowlist[]Which MCP tools this agent may call.
defaultMachineIdPreferred runner.
statusoffline, idle, busy or paused. Derived from heartbeats, never hand-set.
lastSeenAt, concurrencyLimitScheduling inputs.

Persona

The persona is the operating instruction set for the remote session, not decoration. It is the difference between an agent that knows this repository's conventions and one that guesses them. Because it lives in the record rather than in someone's terminal configuration, every machine that runs this agent runs the same one.

toolAllowlist

The allowlist is enforced server-side. The MCP server refuses a tool the agent lacks; it does not merely hide it from the tool list. Hiding is a suggestion, refusing is a rule.

Status is derived

Status is computed from heartbeats and open leases. Nothing sets it by hand, and no UI control writes it. An agent is offline because its machine stopped reporting, not because someone marked it so. This is what makes the status trustworthy enough to route on.

Machine

A physical or remote workstation that can host a runtime.

FieldNotes
hostname, os, archWhat it is.
connectionmcp, api or browser. Which door this machine uses.
enrollmentTokenIdThe credential used to register it.
capabilities[]What it can do, independent of the agents that run on it.
lastHeartbeatAt, statusLiveness.

Machines heartbeat. A machine silent past heartbeatTtl marks its agents offline and releases their leases, which returns their tasks to the queue. Machine liveness is therefore the root of agent liveness: one silent workstation cannot hold a fleet of tasks hostage.

How routing reads them

A claim is a query, not an assignment. When an agent asks for work, the intended inputs are:

  1. Capability filter. The agent's capabilities[] intersected with what the task and its project require.
  2. Priority. The highest-priority ready task wins. See tasks.
  3. Concurrency. An agent at its concurrencyLimit is passed over.
  4. Liveness. An offline agent is not a candidate, and a paused agent is deliberately held out of rotation.
  5. Machine. defaultMachineId is the preferred runner; the machine actually used is recorded on the Run, because the two can differ.

agents_list and machines_list exist so an agent can read this table itself and hand work off to a better-suited peer rather than doing it badly.

Tokens

An ApiKey or AgentToken is a scoped credential for machine access: scopes[], an optional agentId and machineId, expiresAt, lastUsedAt. Tokens are hashed at rest and never returned after creation.

Scoping is per agent and per machine so that one credential can be revoked without touching any other. Every request is logged with the agent id that made it, which is what connects a row in the database to the identity that wrote it.

On this page

GitHubEdit this page on GitHub