From a925c35f1a4a3a193916c3c45ff7defcce79a7a6 Mon Sep 17 00:00:00 2001 From: Jason Robert Date: Thu, 14 May 2026 09:36:58 -0400 Subject: [PATCH] docs(skill): refresh conductor skill with latest features Update the .claude/skills/conductor skill to reflect the current CLI, schema, and feature set: - SKILL.md: add show, replay, --metadata, --workspace-instructions, and update --apply to the quick reference; expand Key Concepts with type: workflow, dialog, retry, hooks, metadata, instructions, agent timeout_seconds, and the openai-agents provider. - references/execution.md: document show, replay, run/resume flag parity (--metadata, --workspace-instructions, --instructions, --web on resume), corrected update behavior (default prints install command; --apply launches installer), CONDUCTOR_NO_UPDATE_CHECK, validate semantic checks, registry latest=branch-HEAD and #ref syntax, and openai-agents provider override. - references/authoring.md: add hooks, metadata, instructions to workflow config; add timeout_seconds, retry, dialog blocks to agent schema; new Sub-Workflow Agents and Dialog Mode sections; document script JSON-stdout auto-merge; add workflow.dir and workflow.file template variables; add openai-agents provider. - references/yaml-schema.md: add metadata and instructions to WorkflowDef; add workflow, input_mapping, max_depth, timeout_seconds, and dialog to AgentDef with full restriction notes; add openai-agents to runtime.provider; document unknown-fields-rejected validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .claude/skills/conductor/SKILL.md | 34 +++- .../skills/conductor/references/authoring.md | 173 +++++++++++++++++- .../skills/conductor/references/execution.md | 126 ++++++++++--- .../conductor/references/yaml-schema.md | 42 ++++- 4 files changed, 327 insertions(+), 48 deletions(-) diff --git a/.claude/skills/conductor/SKILL.md b/.claude/skills/conductor/SKILL.md index 1ebfe55..76ee09f 100644 --- a/.claude/skills/conductor/SKILL.md +++ b/.claude/skills/conductor/SKILL.md @@ -29,13 +29,19 @@ conductor run workflow.yaml -s --input question="Hello" # Silent: JSON result o conductor run workflow.yaml --log-file auto # Log full debug output to file conductor run workflow.yaml --web --input q="Hello" # Real-time web dashboard conductor run workflow.yaml --web-bg --input q="Hello" # Background mode (prints URL, exits) -conductor validate workflow.yaml # Validate only -conductor registry add official myorg/workflows --default # Add a registry +conductor run workflow.yaml -m tracker=ado -m work_item=42 # Attach metadata (merged on top of YAML) +conductor run workflow.yaml --workspace-instructions # Auto-discover AGENTS.md / CLAUDE.md / etc. +conductor validate workflow.yaml # Validate (schema + semantic checks) +conductor show workflow.yaml # Show inputs, agents, and outputs +conductor replay events.jsonl # Replay a recorded run in the dashboard +conductor registry add official myorg/workflows --default # Add a registry (--type github|path) conductor registry list official # List registry workflows conductor run qa-bot@official@1.0.0 --input q="Hello" # Run from registry conductor stop # Stop background workflow -conductor update # Check for and install latest version +conductor update # Check + print install command +conductor update --apply # Check + launch installer (then exit) conductor resume workflow.yaml # Resume from last checkpoint +conductor resume workflow.yaml --web # Resume with dashboard (run-flag parity) conductor checkpoints # List available checkpoints ``` @@ -92,17 +98,25 @@ For runtime config, context modes, limits, and cost tracking, see [references/au |---------|-------------| | `entry_point` | First agent/group to execute | | `routes` | Where agent goes next (`$end` to finish, `self` to loop) | -| `type: script` | Shell command step (captures stdout, stderr, exit_code) | +| `type: script` | Shell command step (captures stdout, stderr, exit_code; JSON stdout is auto-merged) | +| `type: workflow` | Sub-workflow agent — runs another YAML file as a black box (supports `input_mapping`, `max_depth`) | | `parallel` | Static parallel groups (fixed agent list) | -| `for_each` | Dynamic parallel groups (runtime-determined array) | -| `human_gate` | Pauses for user decision with options | +| `for_each` | Dynamic parallel groups (runtime-determined array; supports `type: workflow` agents) | +| `human_gate` | Pauses for user decision with options (Markdown + auto-linkified paths/URLs) | +| `dialog` | Per-agent trigger for conditional multi-turn conversation with the user | +| `retry` | Per-agent retry policy for transient `provider_error` / `timeout` failures | +| `hooks` | Workflow lifecycle expressions: `on_start`, `on_complete`, `on_error` | +| `metadata` | Arbitrary YAML or `--metadata`/`-m` key-values surfaced in `workflow_started` events | +| `instructions` | Workflow-level workspace context (inline strings or `!file` includes) prepended to every prompt | +| `--workspace-instructions` | CLI flag to auto-discover AGENTS.md / CLAUDE.md / `.github/copilot-instructions.md` / `.github/instructions/**/*.instructions.md` (only `applyTo: "**"` files) | | `!file` tag | Include external file content in YAML (`prompt: !file prompt.md`) | | `context.mode` | How agents share data (accumulate, last_only, explicit) | | `limits` | Safety bounds (max_iterations up to 500, timeout_seconds) | +| `timeout_seconds` (agent) | Hard wall-clock cancellation per agent (provider-backed agents only) | | `cost` | Token usage and cost tracking configuration | -| `runtime` | Provider, model, temperature, max_tokens, reasoning effort, MCP servers | -| `--web` | Real-time web dashboard with DAG graph, live streaming, in-browser human gates | -| `checkpoint` | Auto-saved on failure; resume with `conductor resume` | -| `registry` | Named workflow sources (GitHub repo or local dir) for sharing workflows | +| `runtime` | Provider (`copilot`, `claude`, `openai-agents`), model, temperature, max_tokens, reasoning effort, MCP servers | +| `--web` | Real-time web dashboard with DAG graph, live streaming, in-browser human gates, sub-workflow dive-in, replay | +| `checkpoint` | Auto-saved on failure; resume with `conductor resume` (run-flag parity: `--provider`, `--metadata`, `--web`, `--web-bg`, `--web-port`) | +| `registry` | Named workflow sources (GitHub repo or local dir); refs accept `name@registry@version` and `workflow#ref` (tag/branch/SHA) | For pattern examples (linear, loop, conditional, parallel, for-each, human gate) and template syntax, see [references/authoring.md](references/authoring.md). diff --git a/.claude/skills/conductor/references/authoring.md b/.claude/skills/conductor/references/authoring.md index f696cee..7ab76aa 100644 --- a/.claude/skills/conductor/references/authoring.md +++ b/.claude/skills/conductor/references/authoring.md @@ -12,7 +12,7 @@ workflow: entry_point: first_agent # Required: starting agent, parallel group, or for-each group runtime: - provider: copilot # copilot (default) or claude + provider: copilot # copilot (default), claude, or openai-agents default_model: gpt-5.2 # Default model for agents temperature: 0.7 # 0.0-1.0 (optional) max_tokens: 4096 # Max output tokens per response (optional) @@ -42,6 +42,24 @@ workflow: custom-model: input_per_mtok: 3.0 output_per_mtok: 15.0 + + hooks: # Optional lifecycle expressions + on_start: "..." # Evaluated when workflow starts + on_complete: "..." # Evaluated on success + on_error: "..." # Evaluated on failure + + metadata: # Optional arbitrary key-values surfaced in workflow_started events + tracker: ado + work_item_id: 42 + # Merged with --metadata / -m CLI flags (CLI wins on key collision) + + instructions: # Optional workspace context prepended to every agent prompt + - !file ../AGENTS.md # !file include + - "Always respond in English." # Inline string + # For workflows distributed via registry, prefer the --workspace-instructions + # CLI flag (auto-discovers AGENTS.md / CLAUDE.md / .github/copilot-instructions.md + # / .github/instructions/**/*.instructions.md with applyTo: "**") so target-repo + # context is loaded at run time instead of being baked into the YAML. ``` ## Agent Definition @@ -75,7 +93,25 @@ agents: - web_search max_agent_iterations: 100 # Override workflow default for this agent (optional) - max_session_seconds: 60 # Wall-clock timeout for this agent (optional) + max_session_seconds: 60 # Wall-clock timeout for this agent (optional, soft, between iterations) + timeout_seconds: 120 # Hard wall-clock cancellation for this agent (provider-backed only). + # Engine wraps execution in asyncio.wait_for(); raises AgentTimeoutError. + # Effective limit = min(timeout_seconds, remaining_workflow_timeout). + # Non-retryable. Forbidden on script/human_gate/workflow types. + + retry: # Per-agent retry policy (optional, not allowed on script/human_gate/workflow) + max_attempts: 3 # 1-10, default 1 (no retry) + backoff: exponential # exponential (default) or fixed + delay_seconds: 2.0 # Base delay (0-300, default 2.0) + retry_on: # Default: ["provider_error", "timeout"] + - provider_error # API 500s, rate limits + - timeout # Agent-level timeout exceeded + # Validation errors are never retried. + + dialog: # Optional: conditionally pause for free-form conversation (optional) + trigger_prompt: | + Enter dialog if the agent expresses uncertainty about the user's + intent or needs clarification on ambiguous requirements. reasoning: # Override runtime.default_reasoning_effort (optional) effort: high # low, medium, high, or xhigh @@ -179,14 +215,28 @@ agents: ### Script Output -Script steps always produce three fields (no custom `output` schema): +Script steps always produce three fields: ```jinja2 -{{ script_name.output.stdout }} # Captured standard output +{{ script_name.output.stdout }} # Captured standard output (string) {{ script_name.output.stderr }} # Captured standard error {{ script_name.output.exit_code }} # Process exit code (0 = success) ``` +If `stdout` is **valid JSON**, its top-level keys are auto-merged into the agent's output dict alongside `stdout`/`stderr`/`exit_code`. This enables structured `when:` route conditions instead of opaque exit-code matching: + +```yaml +agents: + - name: classify + type: script + command: python3 + args: ["classify.py"] # prints e.g. {"category": "bug", "score": 87} + routes: + - to: bug_handler + when: "category == 'bug'" # field-based, not exit-code-based + - to: triage +``` + ### Script Routing Route conditions use `exit_code` directly (simpleeval syntax): @@ -200,9 +250,120 @@ routes: ### Script Restrictions -Script agents **cannot** have: `prompt`, `provider`, `model`, `tools`, `output`, `system_prompt`, `options`. +Script agents **cannot** have: `prompt`, `provider`, `model`, `tools`, `output`, `system_prompt`, `options`, `retry`, `reasoning`, `dialog`, `max_session_seconds`, `max_agent_iterations`, `timeout_seconds` (use `timeout:` instead), `input_mapping`, or `max_depth`. Command and args support Jinja2 templating for dynamic values. +## Sub-Workflow Agents (`type: workflow`) + +Reference an external workflow YAML file as a black-box step. The sub-workflow runs with its own engine and inherits the parent's provider configuration. + +```yaml +agents: + - name: deep_research + type: workflow + workflow: ./research-pipeline.yaml # Required: path resolved relative to parent YAML + input: # Optional: explicit input declarations (for explicit context mode) + - workflow.input.topic + input_mapping: # Optional: per-call inputs to the sub-workflow + topic: "{{ workflow.input.topic }}" + depth: "{{ research_planner.output.depth }}" + max_depth: 3 # Optional per-agent recursion cap + # (additionally bounded by global MAX_SUBWORKFLOW_DEPTH = 10) + output: # Optional output schema for validation + findings: + type: string + routes: + - to: synthesizer +``` + +**Semantics:** + +- `workflow` path is resolved relative to the parent workflow file. +- Sub-workflow inherits the parent's provider configuration. +- When `input_mapping` is omitted, the parent's `workflow.input.*` is forwarded as-is. +- `input_mapping` keys are sub-workflow input names; values are Jinja2 expressions evaluated against the parent's context. +- Recursive composition is supported with a global `MAX_SUBWORKFLOW_DEPTH = 10`. Self-referential workflows are allowed; bound recursion further with `max_depth`. +- Each invocation emits `subworkflow_started` / `subworkflow_completed` events. The dashboard supports breadcrumb navigation and double-click dive-in. +- Sub-workflow output is accessible via `{{ agent_name.output.field }}`. + +**Sub-workflows in `for_each` groups** — `type: workflow` agents work inside `for_each` groups for dynamic fan-out, with per-iteration `input_mapping` evaluated against the loop variable: + +```yaml +for_each: + - name: plan_issues + type: for_each + source: epic_planner.output.issues + as: issue + max_concurrent: 1 + agent: + type: workflow + workflow: ./plan-and-review.yaml + input_mapping: + work_item_id: "{{ issue.id }}" + title: "{{ issue.title }}" +``` + +**Restrictions** — workflow steps cannot have `prompt`, `model`, `provider`, `tools`, `system_prompt`, `command`, `options`, `retry`, `reasoning`, `dialog`, `max_session_seconds`, `max_agent_iterations`, or `timeout_seconds`. + +## Dialog Mode + +Dialog mode lets an agent conditionally pause after execution and enter a free-form conversation with the user. A lightweight evaluator LLM call inspects the agent's output against `trigger_prompt` and decides whether to engage. Both Copilot and Claude providers are supported, and the dashboard provides dedicated UI (`DialogDetail`, `DialogEngagementPrompt`, `DialogOverlay`). + +```yaml +agents: + - name: researcher + prompt: "Research the given topic thoroughly" + dialog: + trigger_prompt: | + Enter dialog if the agent expresses uncertainty about + the user's intent, encounters ambiguous requirements, + or needs clarification before proceeding. + Do NOT trigger for minor uncertainties the agent can resolve on its own. + routes: + - to: writer +``` + +Only valid on provider-backed agents (not `script`, `human_gate`, or `workflow`). See `examples/dialog-mode.yaml` for a complete example. + +## Workflow Metadata and Workspace Instructions + +### Metadata + +Attach arbitrary key-value metadata to a workflow for downstream tooling (dashboards, work-item trackers, audit logs). Surfaced in the `workflow_started` event payload. + +```yaml +workflow: + name: implement + metadata: + tracker: ado + template_version: 3 +``` + +CLI metadata is merged on top of YAML metadata (CLI wins on key collision; values stay as strings, no type coercion): + +```bash +conductor run workflow.yaml -m work_item_id=1814 -m sprint=Q3 +``` + +### Workspace Instructions + +Prepend workspace context to every agent prompt. Three options: + +1. **YAML `instructions:`** — first-class field, persisted in checkpoints, inherited into sub-workflows. Best for self-contained workflows where the YAML lives alongside the code. + + ```yaml + workflow: + instructions: + - !file ../AGENTS.md + - "Always respond in English." + ``` + +2. **`--workspace-instructions` CLI flag** — auto-discovers files by walking from CWD to the git root: `AGENTS.md`, `CLAUDE.md`, `.github/copilot-instructions.md`, and `.github/instructions/**/*.instructions.md` (only files with `applyTo: "**"` in YAML frontmatter; scoped or absent-`applyTo` files are skipped per the GitHub Copilot convention). Best for workflows distributed via registry/skills where the YAML lives far from the target repo. + +3. **`--instructions PATH` CLI flag** — explicit path to a file (repeatable). + +All three sources are concatenated and prepended to every agent's prompt as a workspace preamble. + ## File Includes (`!file` Tag) Include external file content in YAML using the `!file` tag: @@ -461,6 +622,8 @@ tools: ["search", "fetch"] # Only these tools available |----------|-------------| | `{{ workflow.input.param }}` | Workflow input | | `{{ workflow.name }}` | Workflow name | +| `{{ workflow.dir }}` | Directory of the workflow YAML file (always available, all context modes) | +| `{{ workflow.file }}` | Absolute path to the workflow YAML file | | `{{ agent_name.output.field }}` | Agent output | | `{{ output.field }}` | Current agent output (in routes) | | `{{ group.outputs.agent.field }}` | Parallel group output | diff --git a/.claude/skills/conductor/references/execution.md b/.claude/skills/conductor/references/execution.md index 4afa5cd..9a9e35c 100644 --- a/.claude/skills/conductor/references/execution.md +++ b/.claude/skills/conductor/references/execution.md @@ -16,7 +16,8 @@ conductor run [OPTIONS] |--------|-------------| | `--input`, `-i NAME=VALUE` | Workflow input (repeatable) | | `--input.NAME=VALUE` | Alternative input syntax | -| `--provider`, `-p PROVIDER` | Override provider (copilot, claude) | +| `--metadata`, `-m KEY=VALUE` | Workflow metadata, merged on top of YAML `metadata:` (repeatable; values stay strings) | +| `--provider`, `-p PROVIDER` | Override provider (`copilot`, `claude`, `openai-agents`) | | `--dry-run` | Show execution plan only | | `--skip-gates` | Auto-select first option at human gates | | `--web` | Start real-time web dashboard | @@ -24,6 +25,8 @@ conductor run [OPTIONS] | `--web-port PORT` | Port for web dashboard (0 = auto) | | `--no-interactive` | Disable Esc-to-interrupt capability | | `--log-file`, `-l PATH` | Write full debug output to file (`auto` for auto-generated) | +| `--workspace-instructions` | Auto-discover `AGENTS.md`, `CLAUDE.md`, `.github/copilot-instructions.md`, and `.github/instructions/**/*.instructions.md` (only files marked `applyTo: "**"`) and prepend them to every agent prompt | +| `--instructions PATH` | Path to a specific instruction file to prepend (repeatable) | **Global options** (before the subcommand): @@ -65,6 +68,15 @@ conductor run workflow.yaml --dry-run # Override provider conductor run workflow.yaml -p claude +# Attach metadata (merged on top of YAML metadata; values are strings) +conductor run workflow.yaml -m tracker=ado -m work_item_id=42 + +# Auto-discover workspace instructions and prepend to all prompts +conductor run workflow.yaml --workspace-instructions + +# Prepend explicit instruction file(s) +conductor run workflow.yaml --instructions AGENTS.md --instructions notes.md + # Start real-time web dashboard conductor run workflow.yaml --web --input question="Hello" @@ -106,25 +118,30 @@ conductor stop --all ### conductor update -Check for and install the latest version of Conductor: +Check for the latest version of Conductor and (optionally) launch the installer: ```bash -conductor update +conductor update # Check + print install command +conductor update --apply # Check + launch installer (then exit) ``` The command: -1. Fetches the latest release from the GitHub Releases API -2. Compares the remote version with the locally installed version -3. If a newer version is available, runs `uv tool install --force git+https://github.com/microsoft/conductor.git@v{version}` to upgrade -4. Clears the update-check cache on success so the next invocation re-checks cleanly -If already up to date, prints a confirmation message and exits. +1. Fetches the latest release from the GitHub Releases API. +2. Compares the remote version with the locally installed version. +3. **Default:** prints the OS-appropriate `install.sh` / `install.ps1` one-liner you can paste into a fresh shell. +4. **`--apply`:** spawns the install script as a fully detached process and exits the current `conductor` so file locks release. On Windows the installer opens in a new console window; on POSIX `os.execvpe` replaces the process. This is the only way to upgrade-while-running cleanly on Windows (in-process self-upgrade was removed because the running interpreter sits inside the venv that `uv tool install --force` is trying to recreate). +5. Clears the update-check cache on success. + +If already up to date, prints a confirmation and exits. + +The legacy `--force` flag is accepted as a no-op for backward compatibility. -**Passive update hints:** On every CLI invocation, Conductor checks for updates (cached 24 hours, 2-second timeout) and prints a one-line hint if a newer version is available. Hints only appear when stderr is a TTY and `--silent` is not set. +**Passive update hints:** On every CLI invocation, Conductor checks for updates (cached 24h, 2-second timeout) and prints a one-line hint if a newer version is available. Suppressed when stderr is not a TTY, when `--silent` is set, when the subcommand is `update`, or when `CONDUCTOR_NO_UPDATE_CHECK=1`. ### conductor resume -Resume a workflow from a checkpoint after failure: +Resume a workflow from a checkpoint after failure. Run-flag parity: most `run` flags work identically. ```bash conductor resume [OPTIONS] @@ -134,29 +151,37 @@ conductor resume --from [OPTIONS] | Option | Description | |--------|-------------| | `--from PATH` | Resume from a specific checkpoint file | +| `--provider`, `-p PROVIDER` | Override provider for the resumed run | +| `--metadata`, `-m KEY=VALUE` | Workflow metadata, merged on top of YAML metadata (repeatable) | | `--skip-gates` | Auto-select first option at human gates | | `--log-file`, `-l PATH` | Write debug output to file | | `--no-interactive` | Disable Esc-to-interrupt | +| `--web` | Start real-time web dashboard for the resumed run | +| `--web-port PORT` | Port for the dashboard (0 = auto) | +| `--web-bg` | Fork a detached resume + dashboard process and exit | -When a workflow fails, Conductor automatically saves a checkpoint to `$TMPDIR/conductor/checkpoints/`. The checkpoint contains all prior agent outputs and workflow state, enabling seamless resumption from the failed agent. +`--web` and `--web-bg` are mutually exclusive. The dashboard only shows events from the resumed agent forward — events emitted in the original process before the checkpoint are not replayed. + +Intentionally **not** mirrored on `resume`: `--input` / `--workspace-instructions` / `--instructions` (restored from the checkpoint), and `--dry-run` (incompatible with mid-run resumption). + +When a workflow fails, Conductor automatically saves a checkpoint to `$TMPDIR/conductor/checkpoints/`. The checkpoint contains all prior agent outputs, the workflow state, and the resolved `instructions_preamble`, enabling seamless resumption from the failed agent. **Examples:** ```bash -# Resume the latest checkpoint for a workflow -conductor resume workflow.yaml - -# Resume from a specific checkpoint file +conductor resume workflow.yaml # latest checkpoint conductor resume --from /tmp/conductor/checkpoints/my-workflow-20260303-153000.json - -# Resume with log file +conductor resume workflow.yaml --provider claude +conductor resume workflow.yaml --metadata tracker=ado -m work_item_id=42 +conductor resume workflow.yaml --web +conductor resume workflow.yaml --web-bg conductor resume workflow.yaml --log-file auto ``` **Behavior:** -- If the workflow file has changed since the checkpoint was saved, a warning is displayed +- If the workflow file has changed since the checkpoint was saved, a warning is displayed but resumption proceeds - Execution resumes from the exact agent that failed -- All prior agent outputs are restored from the checkpoint +- All prior agent outputs and the workspace `instructions_preamble` are restored from the checkpoint ### conductor checkpoints @@ -186,14 +211,54 @@ Validate without executing: conductor validate ``` -Checks: +Performs both schema and **semantic** checks: + - YAML syntax -- Required fields and schema structure +- Required fields and schema structure (unknown fields on `AgentDef`, `ParallelGroup`, `ForEachDef`, and `WorkflowConfig` are rejected, not silently dropped) - Agent references and route targets -- Route reachability +- Route reachability and `$end` reachability - Template syntax - Parallel group agent references -- For-each source format and reserved names +- For-each `source` format and reserved names +- Stale agent references and undeclared explicit-mode dependencies in `prompt`, `system_prompt`, `command`, `args`, `working_dir`, `input_mapping`, parallel-group inputs, and workflow `output:` templates +- Warning when an agent defines `system_prompt` but no `prompt:` (portability hazard since the Claude provider drops `system_prompt`) + +The success summary table includes Parallel Groups and For-each Groups counts. + +### conductor show + +Show inputs, agents, parallel/for-each groups, and outputs for a workflow without running it. Accepts a local file path or a registry reference. + +```bash +conductor show +``` + +**Examples:** + +```bash +conductor show ./my-workflow.yaml +conductor show qa-bot +conductor show qa-bot@my-registry@1.0.0 +``` + +Prints a sample `conductor run …` command pre-populated with the discovered inputs. + +### conductor replay + +Replay a recorded workflow run in the dashboard with a timeline scrubber: + +```bash +conductor replay [--web-port PORT] +``` + +The log file can be: +- A JSON array downloaded from the dashboard (`GET /api/logs`) +- A JSONL file written by the `EventLogSubscriber` (e.g. `$TMPDIR/conductor/conductor--.events.jsonl`) + +```bash +conductor replay conductor-logs.json +conductor replay /tmp/conductor/conductor-my-workflow-20260101-120000.events.jsonl +``` ### conductor registry @@ -205,8 +270,8 @@ conductor registry [OPTIONS] | Subcommand | Description | |------------|-------------| -| `list [name]` | List registries, or workflows in a specific registry | -| `add ` | Add a registry (`--type github\|path`, `--default`) | +| `list [name]` | List registries, or workflows in a specific registry (also shows latest tags) | +| `add ` | Add a registry. Options: `--type github\|path` (default github), `--default` | | `remove ` | Remove a registry | | `set-default ` | Set the default registry | | `update [name]` | Refresh index and re-resolve latest versions | @@ -231,9 +296,11 @@ conductor run qa-bot # latest from default registry conductor run qa-bot@official # latest from named registry conductor run qa-bot@official@1.2.3 # explicit version conductor run qa-bot@@1.2.3 # explicit version from default registry +conductor run sdd/plan#main # branch/tag/SHA via "#ref" suffix +conductor run sdd/plan#abc1234 # explicit commit ``` -Registry workflows are cached locally at `~/.conductor/cache/registries/` and reused on subsequent runs. Explicit versions are immutable; `latest` is re-resolved on `conductor registry update`. +`latest` (and bare `name@registry` refs without a `#ref`) resolve to the **default branch HEAD**, not the newest tag — pin explicitly with `workflow#v1.2.3` for releases. Registry workflows are cached locally at `~/.conductor/cache/registries/`. Explicit refs are immutable; bare names re-resolve on `conductor registry update`. ## Execution Flow @@ -487,8 +554,9 @@ If the workflow file has changed since the checkpoint was saved, a warning is di ### Override Provider ```bash -conductor run workflow.yaml -p claude # Use Claude for all agents -conductor run workflow.yaml -p copilot # Use Copilot (default) +conductor run workflow.yaml -p claude # Use Claude for all agents +conductor run workflow.yaml -p copilot # Use Copilot (default) +conductor run workflow.yaml -p openai-agents # Use OpenAI Agents SDK ``` ### Per-Agent Provider Override @@ -532,7 +600,9 @@ conductor run workflow.yaml --input q="test" | jq '.answer' |----------|-------------| | `GITHUB_TOKEN` | GitHub Copilot authentication | | `ANTHROPIC_API_KEY` | Claude provider API key | +| `OPENAI_API_KEY` | OpenAI Agents provider API key (when `provider: openai-agents`) | | `CONDUCTOR_LOG_LEVEL` | Logging level (DEBUG, INFO, WARNING, ERROR) | +| `CONDUCTOR_NO_UPDATE_CHECK` | Set to `1` to suppress the passive update-check hint | Environment variables in YAML configs support `${VAR}` and `${VAR:-default}` interpolation syntax. diff --git a/.claude/skills/conductor/references/yaml-schema.md b/.claude/skills/conductor/references/yaml-schema.md index ccd7d54..a2be3bf 100644 --- a/.claude/skills/conductor/references/yaml-schema.md +++ b/.claude/skills/conductor/references/yaml-schema.md @@ -27,7 +27,7 @@ workflow: # Runtime configuration runtime: - provider: string # "copilot" (default) or "claude" + provider: string # "copilot" (default), "claude", or "openai-agents" default_model: string # Default model for all agents temperature: float # 0.0-1.0, controls randomness (optional) max_tokens: integer # Max OUTPUT tokens per response, 1-200000 (optional) @@ -81,6 +81,18 @@ workflow: on_start: string # Template executed at workflow start on_complete: string # Template executed on success on_error: string # Template executed on failure + + # Arbitrary metadata for downstream tooling (dashboards, work-item trackers) + # Surfaced verbatim in the workflow_started event. + metadata: {string: any} # Optional. Merged with --metadata / -m CLI flags (CLI wins). + + # Workspace context prepended to every agent prompt + # Each entry is either a !file include or an inline string. + # For workflows distributed via registry, prefer the --workspace-instructions + # CLI flag for runtime auto-discovery. + instructions: + - !file ../AGENTS.md + - "Always respond in English." ``` ## Agent Schema @@ -129,21 +141,36 @@ agents: # Agent-level limits (override workflow runtime defaults) max_agent_iterations: integer # Max tool-use roundtrips for this agent (1-500, optional) - max_session_seconds: float # Wall-clock timeout for this agent session (optional) + max_session_seconds: float # Soft wall-clock timeout per session (checked between iterations) + timeout_seconds: float # Hard wall-clock timeout (>=1.0); engine wraps in asyncio.wait_for(). + # Effective limit = min(timeout_seconds, remaining_workflow_timeout). + # Raises AgentTimeoutError; non-retryable. + # Forbidden on script (use 'timeout' instead), human_gate, workflow. # Per-agent reasoning effort (overrides runtime.default_reasoning_effort) # Not allowed for script, human_gate, or workflow agent types. reasoning: effort: string # low, medium, high, or xhigh - # Per-agent retry policy (optional, not allowed for script agents) + # Per-agent retry policy (optional, not allowed for script, human_gate, or workflow agents) retry: max_attempts: integer # Max attempts including first (1-10, default: 1 = no retry) backoff: string # "exponential" (default) or "fixed" delay_seconds: float # Base delay in seconds (0-300, default: 2.0) - retry_on: # Error categories to retry (default: all) + retry_on: # Error categories to retry (default: ["provider_error", "timeout"]) - string # "provider_error" (API 500s, rate limits) or "timeout" + # Conditional dialog mode (optional, only on provider-backed agents) + dialog: + trigger_prompt: string # Criteria evaluated against agent output by an LLM gate + + # Sub-workflow fields (type: workflow) + workflow: string # Path to sub-workflow YAML (relative to parent), required + input_mapping: # Optional Jinja2 expressions per sub-workflow input parameter + : string # e.g. "{{ task_manager.output.current_issue_id }}" + max_depth: integer # Optional per-agent recursion cap (1-10). + # Bounded additionally by global MAX_SUBWORKFLOW_DEPTH = 10. + # Script-only fields (type: script) command: string # Command to execute (Jinja2 templated) args: [string] # Command arguments (each Jinja2 templated) @@ -152,7 +179,9 @@ agents: timeout: integer # Per-script timeout in seconds ``` -**Script agent restrictions:** Cannot have `prompt`, `provider`, `model`, `tools`, `output`, `system_prompt`, `options`, `retry`, `reasoning`. Output is always `{stdout, stderr, exit_code}`. +**Script agent restrictions:** Cannot have `prompt`, `provider`, `model`, `tools`, `output`, `system_prompt`, `options`, `retry`, `reasoning`, `dialog`, `max_session_seconds`, `max_agent_iterations`, `timeout_seconds` (use `timeout`), `input_mapping`, or `max_depth`. Output is always `{stdout, stderr, exit_code}`. If `stdout` is valid JSON, its top-level keys are auto-merged into the output dict. + +**Workflow agent restrictions (`type: workflow`):** Cannot have `prompt`, `model`, `provider`, `tools`, `system_prompt`, `command`, `options`, `retry`, `reasoning`, `dialog`, `max_session_seconds`, `max_agent_iterations`, or `timeout_seconds`. Requires `workflow:` path. Supports `input_mapping` and `max_depth`. Allowed inside `for_each` groups for dynamic fan-out. **Reasoning effort:** `reasoning.effort` (and `runtime.default_reasoning_effort`) accepts `low`, `medium`, `high`, or `xhigh`. Per-agent value overrides the runtime default. Each provider translates the unified value to its native API: @@ -365,6 +394,8 @@ output: {{ workflow.input.param_name }} # Workflow input {{ workflow.name }} # Workflow name {{ workflow.description }} # Workflow description +{{ workflow.dir }} # Directory containing the workflow YAML (all context modes) +{{ workflow.file }} # Absolute path to the workflow YAML {{ agent_name.output.field }} # Agent output field {{ output.field }} # Current agent output (in routes) ``` @@ -511,6 +542,7 @@ runtime: - `entry_point` must reference a valid agent, parallel group, or for-each group - All referenced agents/groups must be defined - Input parameter names must be valid identifiers +- Unknown fields on `WorkflowConfig`, `AgentDef`, `ParallelGroup`, and `ForEachDef` are **rejected** (not silently dropped) ### Agent Validation