# Agent daemon

`@fivexer/agent` runs AI agents on your own machines as Fivexer workers. Someone asks for an SEO audit, the matcher picks the worker that fits, and if that worker is an agent on your laptop, this daemon picks the task up, runs it, and reports back.

It is the mirror image of [the MCP server](/docs/agentic/mcp): MCP lets an agent *create* routed work; this lets an agent *receive* it.

## Quick start

On a machine you are sitting at:

```
bashnpx @fivexer/agent init          # opens your browser to sign in
npx @fivexer/agent doctor        # check everything before a task depends on it
npx @fivexer/agent run
```

`init` finds which agent CLIs you already have, asks which should do the work, signs you in through the browser, registers the worker, puts it on shift, and scaffolds a home directory for that agent's own configuration.

### On a machine you are not sitting at

A server or a container, with no browser. Create a join link in the console — picking the tags and skills this agent should have — and hand it over:

```
bashnpm install -g @fivexer/agent
fivexer-agent init --yes --executor claude \
  --join 'https://api.5xer.com/v1/worker-auth/join?token=jl_…'
fivexer-agent service install    # writes a service unit; does not enable it
```

The link is scoped to creating one worker, so it is the right thing to put in a provisioning script.

**No long-lived workspace credential ever lands on the host.** Whichever path you take, what stays on disk is a `wt_` worker session that reaches only its own queue, plus a PIN to renew it. The browser token and the API key are each used once and dropped.

## Vendor-neutral by construction

The daemon spawns a command and reads a JSON file. That works with Claude Code, Codex, OpenCode, Cline, Goose, Aider — or a `#!/bin/sh` script, which is what the test suite runs against. Nothing in it depends on any vendor's protocol.

Presets: `claude`, `codex`, `opencode`, `goose`, `aider`, `cline`. Or name a command yourself.

Capability stays on your host — your MCP servers, your API keys, your browser, your filesystem. Routing, SLA, escalation, and learning stay in Fivexer.

## Commands

|  |  |
| --- | --- |
| `init` | set this machine up: pick an agent, register, scaffold its home |
| `join <link>` | register a profile by redeeming a join link |
| `doctor` | check config, credentials, executors and shift state; claims nothing |
| `run` | work every profile's queue until stopped |
| `once` | one pass over every queue, then exit — for cron, or a smoke test |
| `next` | print the next task and exit |
| `mcp` | speak MCP over stdio, so an interactive agent pulls its own work |
| `service install` | write a user-level systemd / launchd / Scheduled Task unit, unenabled |

## Profiles

A profile **is** a Fivexer worker — its own id, tags, skills, and backlog. Routing between profiles is therefore done by the Fivexer matcher, on the same rules that route work to people. There is no second dispatch layer on your host.

Configuration lives in `~/.fivexer/config.json`, `./fivexer.agent.json`, or `--config`:

```
json{
  "workspaceId": "ws_...",
  "profiles": [
    {
      "name": "research",
      "tags": ["agent", "research", "seo"],
      "skills": [{ "skillId": "seo-audit", "level": 4 }],
      "executor": "claude",
      "cwd": "~/agents/research",
      "workspace": "cwd",
      "passEnv": ["BRAVE_API_KEY"],
      "timeoutMs": 900000
    }
  ]
}
```

Notable defaults: `concurrency` is `1` and also becomes the worker's `maxBacklogSize`; `timeoutMs` is 15 minutes, after which the process group is killed and the task requeued; `passEnv` is empty, so the agent sees no environment variables you have not listed.

`FIVEXER_WORKSPACE_ID`, `FIVEXER_BASE_URL`, `FIVEXER_API_KEY`, `FIVEXER_STATE_DIR`, and `FIVEXER_POLL_INTERVAL_MS` override the file, so one config can be pointed at staging.

## Bringing your own agent

`init` creates `~/.fivexer/agents/<profile>/` and runs the agent there. That directory is yours — Fivexer never reads it:

```
~/.fivexer/agents/research/
  AGENTS.md        # standing instructions for every task this agent handles
  .mcp.json        # this agent's own MCP servers — its capabilities
  .claude/skills/  # Claude Code skills, when that is the executor
  README.md        # generated: where your chosen CLI reads each of these from
```

Two different things are called "skills" and they are not the same. **Agent skills** live in that directory and are what the agent can *do*. **Fivexer skills** live in the workspace catalog, are attached to the worker, and decide which tasks it is *offered*. Keep them honest with each other — an agent whose tags promise more than its tools deliver gets handed work it then has to reject.

## One caveat with join links

A profile registered by a join link carries `"registration": "join"` and an empty `tags` list; its routing lives in the console. Join links do not set a backlog size, so such a worker gets the workspace default rather than the profile's `concurrency`. The daemon still runs no more than `concurrency` tasks, but the matcher may hand it more, and the surplus waits where nobody else can take it. Match the two, or use the API-key path when the backlog matters.
