7.6 KiB
Contractor Agents CLI Design
Purpose
Define the plugin-owned CLI surface for managing contractor-backed OpenClaw agents.
Phase 1 supports Claude only. Gemini remains reserved in the command shape but is not implemented yet.
Command root
openclaw contractor-agents
This should be implemented as a plugin-owned CLI root, not as a patch to openclaw agents add.
Why a separate command root
Current OpenClaw plugin docs show support for plugin CLI registration, but do not document support for extending existing core commands with new flags.
Relevant doc statements:
"Common registration methods: ...
registerCommand/registerCli| CLI commands"
"For plugin-owned root CLI commands, prefer
api.registerCli(..., { descriptors: [...] })..."
This suggests the supported extension seam is plugin-owned CLI trees.
Sources:
Phase 1 command
openclaw contractor-agents add --agent-id <agent-id> --workspace <workspace> --contractor <claude|gemini>
Phase 1 restrictions:
--contractormust currently beclaudegeminiis accepted only as a reserved future value if desired, but should currently fail with a clear not-yet-implemented message unless you intentionally decide to reject it at parsing time
Arguments
Required
--agent-id <agent-id>--workspace <workspace>--contractor <claude|gemini>
Optional, possible later
Not required for first implementation, but likely useful later:
--bridge-model <model-id>--backend <acp-backend>--mode <persistent|oneshot>--json--non-interactive
For now, phase 1 can hardcode the bridge model and runtime defaults.
Behavior of add
For:
openclaw contractor-agents add --agent-id my-agent --workspace /path/to/ws --contractor claude
The CLI should do the following.
Step 1, validate inputs
- ensure
agent-idis provided - ensure workspace exists or is creatable, based on your desired policy
- ensure contractor kind is supported
- ensure target agent does not already exist unless overwrite behavior is explicitly added later
Step 2, create the base OpenClaw agent
Run the equivalent of:
openclaw agents add <agent-id> --workspace <workspace> --model contractor-claude-bridge --non-interactive
Important note:
Earlier review of openclaw agents add docs showed these supported options:
--workspace <dir>--model <id>--agent-dir <dir>--bind <channel[:accountId]>--non-interactive--json
Source:
This means the contractor CLI can compose the existing agent creation flow rather than replacing it.
Step 3, mark the agent as a contractor-backed agent
After agent creation, write contractor metadata so runtime selection and session bridging can identify this agent as contractor-managed.
Proposed config direction:
{
agents: {
list: [
{
id: "my-agent",
model: "contractor-claude-bridge",
runtime: {
type: "contractor",
contractor: {
kind: "claude",
backend: "acp",
mode: "persistent"
}
}
}
]
}
}
Exact schema is still TBD, but the CLI should be the mechanism that writes this state.
Step 4, initialize contractor runtime state
Prepare runtime state for the agent, including a place to store session mappings.
Suggested path:
<workspace>/.openclaw/contractor-agent/
Suggested initial files:
session-map.json
runtime.json
Session mapping responsibility
The CLI does not create Claude sessions immediately unless you explicitly want eager setup.
Recommended phase 1 behavior:
- create agent metadata
- create runtime state directory
- initialize empty mapping file
- defer real Claude session creation to first actual agent turn
This keeps add lightweight and avoids unused contractor sessions.
Suggested future commands
These are not required immediately, but the command tree should reserve room for them.
Status
openclaw contractor-agents status --agent-id <agent-id>
Show:
- contractor kind
- bridge model id
- runtime backend
- session mapping count
- recent activity
List sessions
openclaw contractor-agents sessions --agent-id <agent-id>
Show session mappings for the given contractor-backed agent.
Reset mapping
openclaw contractor-agents reset-session --agent-id <agent-id> --openclaw-session <session-key>
Drop a specific OpenClaw-to-Claude mapping so the next message recreates the Claude session.
Disable
openclaw contractor-agents disable --agent-id <agent-id>
Either:
- remove contractor metadata but keep agent
- or mark the contractor runtime disabled
Semantics TBD.
JSON output
I recommend all subcommands eventually support --json so this can be scripted.
Example success response shape:
{
"ok": true,
"agentId": "my-agent",
"workspace": "/path/to/ws",
"contractor": "claude",
"model": "contractor-claude-bridge",
"runtimeStateDir": "/path/to/ws/.openclaw/contractor-agent"
}
Failure cases
The CLI should fail clearly for:
- unsupported contractor kind
- agent already exists
- workspace invalid or inaccessible
- bridge model plugin not available
- failure in underlying
openclaw agents add - failure writing contractor metadata
If the agent is created successfully but metadata writing fails, the CLI should either:
- roll back the created agent if safe and simple
- or return a partial-failure error with explicit cleanup instructions
Phase 1 recommendation: prefer explicit rollback if implementation is reliable.
Interaction with the bridge model
The CLI should not directly run Claude Code or create a Claude contractor session by default.
Its main job is to provision an agent whose primary model is the contractor bridge model:
contractor-claude-bridge
That model then handles runtime dispatch during actual conversation turns.
Implementation notes
The plugin should register a root command owned by the plugin.
Relevant doc statements:
"For plugin-owned root CLI commands, prefer
api.registerCli(..., { descriptors: [...] })when you want the command to stay lazy-loaded without disappearing from the root CLI parse tree."
Source:
So the intended shape is:
- plugin registers
contractor-agents - plugin owns parsing and handling of its subcommands
- plugin composes
openclaw agents addbehavior internally or via shared config/runtime helpers
Open questions
- Should the CLI shell out to
openclaw agents addor use a lower-level config/runtime helper directly? - Where should contractor metadata live,
agents.list[].runtime, plugin config, or both? - Should
geminibe rejected now or accepted with a not implemented error? - Should add create the workspace if it does not exist?
- Should agent creation be rolled back if contractor metadata writing fails?
References
Plugin CLI support
"Common registration methods: ...
registerCommand/registerCli| CLI commands"
Source:
Plugin-owned CLI descriptors
"For plugin-owned root CLI commands, prefer
api.registerCli(..., { descriptors: [...] })..."
Source:
Existing agent creation command
agents add [name]
--workspace <dir>--model <id>--agent-dir <dir>--bind <channel[:accountId]>--non-interactive--json
Source: