Files
open-multi-agent/docs/cli.md
T
Jack Chen 0488362c0d feat(orchestrator): error-aware task retry (classify, jitter, honor abort) (#346)
Error-aware task retry (opt-in via maxRetries > 0):

- Skip retries on provably-terminal failures (4xx client errors except
  408/409/429, token-budget, invalid-message, aborted calls).
- Equal jitter on backoff to avoid lockstep retries against a rate-limited
  provider.
- Honor abortSignal between attempts (no full-backoff sleep or extra attempt
  after cancel).
- Non-streaming path preserves the structured error on AgentRunResult.error so
  classification works off the default runTeam path; test-covered.

Off by default; behavior changes only when retry is enabled.

Closes #337
2026-07-01 17:22:54 +08:00

278 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Command-line interface (`oma`)
The package ships a small binary **`oma`** that exposes the same primitives as the TypeScript API: `runTeam`, `runTasks`, plus a static provider reference. It is meant for **shell scripts and CI** (JSON on stdout, stable exit codes).
It does **not** provide an interactive REPL, working-directory injection into tools, human approval gates, or session persistence. Those stay in application code.
## Installation and invocation
After installing the package, the binary is on `PATH` when using `npx` or a local `node_modules/.bin`:
```bash
npm install @open-multi-agent/core
npx oma help
```
From a clone of the repository you need a build first:
```bash
npm run build
node packages/core/dist/cli/oma.js help
```
Set the usual provider API keys in the environment (see [README](../packages/core/README.md#quick-start)); the CLI does not read secrets from flags. MiniMax additionally reads `MINIMAX_BASE_URL` to select the global (`https://api.minimax.io/v1`) or China (`https://api.minimaxi.com/v1`) endpoint. MiMo additionally reads `MIMO_BASE_URL` for Token Plan cluster endpoints such as `https://token-plan-cn.xiaomimimo.com/v1`.
OpenRouter works through the OpenAI-compatible adapter: set `provider` to `openai`, `baseURL` to `https://openrouter.ai/api/v1`, and pass `OPENROUTER_API_KEY` as the agent or orchestrator `apiKey`.
---
## Commands
### `oma run`
Runs **`OpenMultiAgent.runTeam(team, goal)`**: coordinator decomposition, task queue, optional synthesis.
When invoked with `--dashboard`, the **`oma` CLI** writes a static post-execution DAG dashboard HTML to `oma-dashboards/runTeam-<timestamp>.html` under the current working directory (the library does not write files itself; if you want this outside the CLI, call `renderTeamRunDashboard(result)` in application code — see `packages/core/src/dashboard/render-team-run-dashboard.ts`).
The dashboard page is self-contained: it does not load remote scripts, stylesheets, or fonts, and sensitive-looking values in the embedded run payload are redacted before rendering.
| Argument | Required | Description |
|----------|----------|-------------|
| `--goal` | Yes | Natural-language goal passed to the team run. |
| `--team` | Yes | Path to JSON (see [Team file](#team-file)). |
| `--orchestrator` | No | Path to JSON merged into `new OpenMultiAgent(...)` after any orchestrator fragment from the team file. |
| `--coordinator` | No | Path to JSON passed as `runTeam(..., { coordinator })` (`CoordinatorConfig`). |
| `--dashboard` | No | Write a post-execution DAG dashboard HTML to `oma-dashboards/runTeam-<timestamp>.html`. |
Global flags: [`--pretty`](#output-flags), [`--include-messages`](#output-flags).
### `oma task`
Runs **`OpenMultiAgent.runTasks(team, tasks)`** with a fixed task list (no coordinator decomposition).
| Argument | Required | Description |
|----------|----------|-------------|
| `--file` | Yes | Path to [tasks file](#tasks-file). |
| `--team` | No | Path to JSON `TeamConfig`. When set, overrides the `team` object inside `--file`. |
Global flags: [`--pretty`](#output-flags), [`--include-messages`](#output-flags).
### `oma provider`
Read-only helper for wiring JSON configs and env vars.
- **`oma provider`** or **`oma provider list`** — Prints JSON: built-in provider ids, API key environment variable names, whether `baseURL` is supported, and short notes (e.g. OpenAI-compatible servers, Copilot in CI).
- **`oma provider template <provider>`** — Prints a JSON object with example `orchestrator` and `agent` fields plus placeholder `env` entries. `<provider>` is one of: `anthropic`, `azure-openai`, `openai`, `gemini`, `grok`, `minimax`, `mimo`, `deepseek`, `doubao`, `qiniu`, `copilot`, `bedrock`.
For OpenRouter, use the `openai` provider template, set `baseURL` to `https://openrouter.ai/api/v1`, and set `apiKey` from `OPENROUTER_API_KEY` in your JSON config.
Supports `--pretty`.
### `oma`, `oma help`, `oma -h`, `oma --help`
Prints usage text to stdout and exits **0**.
---
## Configuration files
Shapes match the library types `TeamConfig`, `OrchestratorConfig`, `CoordinatorConfig`, and the task objects accepted by `runTasks()`.
### Team file
Used with **`oma run --team`** (and optionally **`oma task --team`**).
**Option A — plain `TeamConfig`**
```json
{
"name": "api-team",
"agents": [
{
"name": "architect",
"model": "claude-sonnet-4-6",
"provider": "anthropic",
"systemPrompt": "You design APIs.",
"tools": ["file_read", "file_write"],
"maxTurns": 6
}
],
"sharedMemory": true
}
```
**Option B — team plus default orchestrator settings**
```json
{
"team": {
"name": "api-team",
"agents": [{ "name": "worker", "model": "claude-sonnet-4-6", "systemPrompt": "…" }]
},
"orchestrator": {
"defaultModel": "claude-sonnet-4-6",
"defaultProvider": "anthropic",
"maxConcurrency": 3
}
}
```
Validation rules enforced by the CLI:
- Root (or `team`) must be an object.
- `team.name` is a non-empty string.
- `team.agents` is a non-empty array; each agent must have non-empty `name` and `model`.
Any other fields are passed through to the library as in TypeScript.
**SDK-only fields**: `sharedMemoryStore` (custom `MemoryStore` instance) cannot be set from JSON since it is a runtime object. Use `sharedMemory: true` for the default in-memory store, or wire a custom store in TypeScript via `orchestrator.createTeam()`.
### Tasks file
Used with **`oma task --file`**.
```json
{
"orchestrator": {
"defaultModel": "claude-sonnet-4-6"
},
"team": {
"name": "pipeline",
"agents": [
{ "name": "designer", "model": "claude-sonnet-4-6", "systemPrompt": "…" },
{ "name": "builder", "model": "claude-sonnet-4-6", "systemPrompt": "…" }
],
"sharedMemory": true
},
"tasks": [
{
"title": "Design",
"description": "Produce a short spec for the feature.",
"assignee": "designer"
},
{
"title": "Implement",
"description": "Implement from the design.",
"assignee": "builder",
"dependsOn": ["Design"]
}
]
}
```
- **`dependsOn`** — Task titles (not internal ids), same convention as the coordinator output in the library.
- Optional per-task fields: `memoryScope` (`"dependencies"` \| `"all"`), `maxRetries`, `retryDelayMs`, `retryBackoff`. When retry is enabled (`maxRetries > 0`), backoff is jittered and provably-terminal failures — 4xx client errors other than 408/409/429, plus token-budget and invalid-message errors — skip retries automatically; no extra config.
- **`tasks`** must be a non-empty array; each item needs string `title` and `description`.
If **`--team path.json`** is passed, the file’s top-level `team` property is ignored and the external file is used instead (useful when the same team definition is shared across several pipeline files).
### Orchestrator and coordinator JSON
These files are arbitrary JSON objects merged into **`OrchestratorConfig`** and **`CoordinatorConfig`**. Function-valued options (`onProgress`, `onApproval`, etc.) cannot appear in JSON and are not supported by the CLI.
Set `defaultCwd` on the orchestrator JSON, or `cwd` on individual agents/coordinator JSON, to choose the sandbox root for built-in filesystem tools. Paths passed to `file_read`, `file_write`, `file_edit`, `grep`, and `glob` must be absolute and resolve inside that root. When `defaultCwd` is omitted, the sandbox defaults to `<cwd>/.agent-workspace` (auto-created on first write). Pass the string `"<process.cwd()>"`-equivalent absolute path to widen it to the full working directory, or `null` to disable the sandbox. The `bash` tool is intentionally not covered — see `docs/tool-configuration.md` for the rationale and recommended posture.
---
## Output
### Stdout
Every invocation prints **one JSON document** to stdout, followed by a newline.
**Successful `run` / `task`**
```json
{
"command": "run",
"success": true,
"goal": "Build a REST API with token auth",
"tasks": [
{
"id": "task-1",
"title": "Design the database schema",
"assignee": "architect",
"status": "completed",
"dependsOn": []
}
],
"totalTokenUsage": { "input_tokens": 0, "output_tokens": 0 },
"agentResults": {
"architect": {
"success": true,
"output": "…",
"tokenUsage": { "input_tokens": 0, "output_tokens": 0 },
"toolCalls": [],
"structured": null,
"loopDetected": false,
"budgetExceeded": false
}
}
}
```
`agentResults` keys are agent names. When an agent ran multiple tasks, the library merges results; the CLI mirrors the merged `AgentRunResult` fields.
**Errors (usage, validation, I/O, runtime)**
```json
{
"error": {
"kind": "usage",
"message": "--goal and --team are required"
}
}
```
`kind` is one of: `usage`, `validation`, `io`, `runtime`, or `internal` (uncaught errors in the outer handler).
### Output flags
| Flag | Effect |
|------|--------|
| `--pretty` | Pretty-print JSON with indentation. |
| `--include-messages` | Include each agent’s full `messages` array in `agentResults`. **Very large** for long runs; default is omit. |
There is no separate progress stream; for rich telemetry use the TypeScript API with `onProgress` / `onTrace`.
---
## Exit codes
| Code | Meaning |
|------|---------|
| **0** | Success: `run`/`task` finished with `success === true`, or help / `provider` completed normally. |
| **1** | Run finished but **`success === false`** (agent or task failure as reported by the library). |
| **2** | Usage, validation, readable JSON errors, or file access issues (e.g. missing file). |
| **3** | Unexpected error, including typical LLM/API failures surfaced as thrown errors. |
In scripts:
```bash
npx oma run --goal "Summarize README" --team team.json > result.json
code=$?
case $code in
0) echo "OK" ;;
1) echo "Run reported failure — inspect result.json" ;;
2) echo "Bad inputs or files" ;;
3) echo "Crash or API error" ;;
esac
```
---
## Argument parsing
- Long options only: `--goal`, `--team`, `--file`, etc.
- Values may be attached with `=`: `--team=./team.json`.
- Boolean-style flags (`--pretty`, `--include-messages`) take no value; if the next token does not start with `--`, it is treated as the value of the previous option (standard `getopt`-style pairing).
---
## Limitations (by design)
- No TTY session, history, or `stdin` goal input.
- No dedicated flag for the filesystem sandbox root; configure it through `defaultCwd` / `cwd` in the orchestrator or agent JSON.
- No **`onApproval`** from JSON; non-interactive batch only.
- Coordinator **`runTeam`** path still requires network and API keys like any other run.