# AGENTS

## Purpose

`agentcli` is the agent-native control plane for workflow manifests. It is not the durable runtime.

Use this repo when the task is about:

- manifest authoring
- validation
- compile target behavior
- scheduler inspection surfaces
- JSON-RPC / MCP style integration

Do not reimplement scheduler durability here. Runtime concerns belong in `openclaw-scheduler`.

## Working Rules

- Prefer machine-readable output and raw JSON payloads.
- Pass `--json` to force structured JSON output from any command (including `help`), except `serve` which runs the JSON-RPC server on stdio.
- Keep manifests backend-portable unless the task explicitly targets `openclaw-scheduler`.
- Default compile target is `standalone`.
- Treat `openclaw-scheduler` as an adapter/backend, not as the core abstraction.
- Preserve agent-safe behavior: safe output paths, strict validation, field masks, and sanitization.

## Error Handling

All CLI errors are written to stderr as JSON with the following shape:

```json
{
  "ok": false,
  "error": "Human-readable error message",
  "error_type": "validation_error | unknown_command | invalid_argument | parse_error | internal_error"
}
```

Use `error_type` for structured dispatch rather than parsing the `error` string. Validation errors include an additional `validation` field with the full error and warning arrays.

## Discovery Flow

When first interacting with `agentcli`, use this sequence:

1. `agentcli version` -- confirm the package and manifest spec version
2. `agentcli describe commands` -- enumerate all available CLI commands
3. `agentcli describe rpc` -- enumerate JSON-RPC methods and notifications
4. `agentcli targets` -- list available compile targets with capabilities
5. `agentcli schema manifest` -- get the machine-readable manifest schema

For JSON-RPC integrations, use `agentcli.version` and `agentcli.describe` with `target: "rpc"` to discover the method surface programmatically.

## Useful Commands

- `agentcli version` -- show package and manifest spec version
- `agentcli init` -- bootstrap a local home directory with a starter manifest
- `agentcli targets` -- list available compilation targets
- `agentcli paths` -- show resolved home directory layout
- `agentcli schema manifest` -- emit machine-readable schema for the manifest format
- `agentcli describe commands` -- list all CLI commands with summaries
- `agentcli validate examples/hello-world.json`
- `agentcli compile examples/hello-world.json --target standalone --explain`
- `agentcli compile examples/hello-world.json --target openclaw-scheduler`
- `agentcli apply <manifest> --adopt-by name --dry-run` -- preview migration of existing scheduler jobs
- `agentcli inspect jobs --db /path/to/scheduler.sqlite --fields id,status`
- `agentcli approve <manifest> <task-id> --by <principal> --reason <text>` -- grant a local single-use approval for a gated task
- `agentcli approvals list [--status pending|consumed|expired|revoked|all]` -- list approval records
- `agentcli approvals revoke <approval-id> --by <principal> --reason <text>` -- revoke a pending approval
- `agentcli exec <manifest> <task-id> --approval-id <id>` -- target a specific pending grant
- `agentcli serve`

<!-- coord:begin -->
<!-- AUTO-GENERATED by 'coord upgrade'. Do not hand-edit; next upgrade will overwrite. -->
## Coordination protocol (mandatory)

Multi-agent file coordination via the `coord` MCP server. Required calls every session:

1. `list_claims` at task start.
2. `claim_files` before editing.
3. `release_claims` (or `release_session` to drop everything this MCP session holds, v0.6+) when done.

If `claim_files` returns conflicts, stop and ask the user. No edits outside claimed scope; no opportunistic refactors; shared config edits only with explicit user approval.

### Repo-scoped tokens (v0.42+)

On a shared coord service that fronts several repos, use a **repo-scoped token** so you only ever see and touch your own repo's claims. The server enforces the scope from the token, so `list_claims` / `check_conflicts` return just your repo no matter what the client sends.

If a tool result carries a `coord_notice` -- or `coord status` prints a `Token warning:` line -- your token is **unscoped** and deprecated: on a shared service it sees and can affect every repo's claims. It is still honored for now, but switch. Ask an operator for a scoped token and drop it in `.coordination/local.env`:

- `coord tokens create <engineer> --repo <owner/name>`

Operator-wide reads are opt-in with `all_repos=True` (a scoped token gets a 403, not a silent all-repo view). Rollout detail: `docs/deployment.md`.

### Sub-file (symbol-level) claims (v0.14+)

When two agents need different parts of the same file, claim symbols instead of whole files. Pass `symbols={"src/auth/login.ts": ["handleLogin"]}` to `claim_files` so the claim scopes to just that function. Two agents on disjoint symbols of the same file auto-coexist with no 409.

- `Foo::handleA` (v0.16): method-level notation. Sibling methods of the same class auto-coexist; the bare class blocks all of its methods.
- `Outer::Inner::method` (v0.17): recursive nesting works to any depth.
- Server-side validation (v0.17): when `COORD_REPO_ROOT` is set, the server rejects symbols that do not exist in the file with a hint listing what is parseable. The MCP wrapper pre-validates locally before POST so typos fail fast; disable with `COORD_DISABLE_CLIENT_VALIDATION=1`.

### Queueing instead of bouncing (v0.21+)

When a hot file is contested and your work is blocking the team, pass `wait_seconds=60` to `claim_files`. The request joins a FIFO queue behind the blocking holder; on release the next queued requester is auto-granted. Pair with `urgency='low' | 'normal' | 'high' | 'blocking'` (v0.25) to jump ahead of lower-priority waiters; long-waiting entries age-boost one level after `COORD_QUEUE_AGE_BOOST_SECONDS` (v0.26). Abandon a wait early via `cancel_queue_request(queue_id, engineer=...)` (v0.26). Inspect your own queue rows via `my_requests(queued=True)` (v0.22).

### Asking the holder directly (v0.6+ / v0.11+ decisions)

If queueing will not work either:
- `request_release` files an explicit ask against the holder's claim. The holder's TTL shortens; their decision lands back in your `my_requests` view.
- `respond_to_request` decisions (v0.11+): `approved` (release whole claim), `denied` (keep it), `narrowed` (close the claim, open a tighter one -- pass `narrowed_pattern`), `coexist` (let the requester have a sibling claim on the same scope -- pass `coexist_pattern`). `coexist` is cooperative not enforced; agents on the same file still handle imports and module-level state themselves.

### Operator visibility

Poll `pending_requests` between operations to see who is blocked on your scope and respond via `respond_to_request`. The dashboard surfaces hotspot files, an auto-resolution heatmap, and a pending-queue panel for ambient awareness.
<!-- coord:end -->
