Evaluation scenarios for testing the Conductor workflow skill end-to-end.
These evaluations ensure the Conductor skill:
npm install -g, never echoes secrets)Tests first-time setup: CLI installation, server choice (local vs remote), auth detection, profile saving.
Tests starting a local Conductor server and creating a first workflow from scratch.
Tests connecting to a remote server URL, detecting auth requirements (401/403), setting credentials, and saving as a profile.
Tests multi-environment queries (e.g. “how many workflows in dev vs prod?”) using --profile to route to the correct server.
Tests full workflow lifecycle: JSON creation, registration, worker check against task definitions, execution, and status monitoring.
Tests searching running workflows, identifying pending WAIT/HUMAN tasks, signaling them, and verifying progression.
Tests finding failed workflows, diagnosing root causes from task details, and retrying them.
Tests fetching a workflow definition and generating a Mermaid flowchart with correct construct mapping.
Tests scaffolding a worker for a SIMPLE task using the appropriate SDK.
Tests the fallback path when Node.js/npm cannot be installed, using the bundled conductor_api.py script.
Tests review/optimization of an existing workflow — loading the workflow + each SIMPLE task’s task def, walking the 22-rule checklist in references/optimization.md (covers LLM-specific gotchas like jsonOutput without “JSON” in prompt and previousResponseId provider lock-in), grouping findings by CRITICAL/WARN/INFO, and offering fixes one at a time without applying silently.
Tests natural-language activation — when a user asks “what can you help me do with Conductor?” the agent should activate from the skill description (no slash command needed) and summarize the major capability areas, including that schedules are OSS.
Tests first-time setup — checking for the CLI, preferring npx, asking before npm install -g, presenting local-vs-remote options, never echoing auth secrets, and verifying with conductor workflow list.
Tests worker scaffolding in the user’s language — first verifying there’s no built-in task that fits (Rule 6), then asking the language, then WebFetching the SDK repo README before writing code (Rule 7), using the correct SDK pattern from references/workers.md, matching the task_definition_name to the workflow’s SIMPLE task name, and including the idempotency note.
Tests scheduling a workflow on cron — recognizing that schedules are OSS (not Orkes), writing the JSON to a file, using correct Quartz cron syntax (including the day-of-month vs day-of-week ? quirk), and registering via conductor schedule create.
Tests building the canonical first-AI-agent workflow — 4 tasks (LIST_MCP_TOOLS → LLM_CHAT_COMPLETE plan → CALL_MCP_TOOL → LLM_CHAT_COMPLETE summarize), low-temperature planning that emits JSON, and correct wiring of ${plan.output.result.method} into the tool call.
Tests building a RAG workflow — LLM_SEARCH_INDEX followed by a grounded LLM_CHAT_COMPLETE, including a system prompt that instructs the model to answer only from context, low temperature, and returning sources alongside the answer.
Tests building a ReAct-pattern autonomous agent loop with the full production-grade scaffold — DO_WHILE with evaluatorType: "graaljs", IIFE loopCondition, hard iteration cap (per optimization rule B5), the canonical self-reference pattern (loop: ${loop.output}), SET_VARIABLE message accumulation, LLM_CHAT_COMPLETE with jsonOutput: true and Conductor’s {role, message} schema, SWITCH with empty defaultCase, JSON_JQ_TRANSFORM with tojson to stringify tool output, optional HTTP tools, and workflow-level timeout.
Tests the GraalJS rules for DO_WHILE loops: evaluatorType: "graaljs" at the top of the DO_WHILE task, IIFE form for loopCondition, $.workflow.* is NOT in scope inside the script (workflow inputs/variables must be plumbed through inputParameters), the $.varName rule, and the ${loop_ref.output.iteration} vs ${loop_ref.iteration} access path.
Tests LLM_CHAT_COMPLETE schema and jsonOutput behavior: messages use Conductor’s {role, message} (NOT the native LLM {role, content}), jsonOutput: true for parsed results, the strict-Jackson-parse pitfall (markdown fences fail), SWITCH with empty defaultCase to absorb malformed LLM emissions, and correct ${task.output.result.field} access paths.
Tests choosing the right tool to serialize structured task output into a string field — JSON_JQ_TRANSFORM with tojson, NOT INLINE. Verifies the agent recognizes the Java-Map-backed proxy hazards: String($.x) produces {k=v} (Java toString), JSON.stringify returns "{}", Object.keys returns []. Interpolating an object directly into a string field also yields {k=v} garbage.
Tests OpenAI Responses API chaining via previousResponseId — turn 1 carries the full prompt, turns 2+ contain only the new user message and reference the prior turn’s ${turnN.output.responseId}. Verifies the agent uses Conductor’s {role, message} schema, chains each turn to the immediately preceding one (not always turn 1), warns about provider lock-in (OpenAI/Azure-only, mid-chain provider switch breaks the chain) and the responseId retention bound.
Tests provider-native built-in tools — webSearch: true (real-time web search; OpenAI/Anthropic/Gemini) and codeInterpreter: true (sandboxed code execution; same providers). Verifies the agent reaches for these instead of inventing an MCP server, custom HTTP fetcher, or custom Conductor worker when the task naturally calls for them.
Tests that the agent defaults to built-in LLM tasks (LLM_CHAT_COMPLETE etc.) instead of raw HTTP tasks to LLM-provider APIs (api.anthropic.com, api.openai.com, etc.) — even when the user volunteers that the HTTP path has worked before. Also tests that the optimization review flags an existing HTTP-to-LLM-provider task as CRITICAL under rule B10 and proposes a converted LLM_CHAT_COMPLETE workflow.
Generalized prefer-built-in test covering non-LLM operations — Kafka publish and PDF generation. Verifies the agent picks KAFKA_PUBLISH over a custom kafka-python worker and GENERATE_PDF over an HTTP-to-wkhtmltopdf service, even when the user volunteers they were about to take those paths. Maps to SKILL.md Rule 6 and optimization rule E4 (reinventing a built-in).
Happy-path evals dominate the suite above. The five evals below stress the agent in adversarial or under-specified scenarios — capitulation under pressure, security antipatterns at creation time, ambiguous/incomplete prompts, conflicting requirements. These are intentionally hard.
The user has read the skill, rejects the LLM_CHAT_COMPLETE recommendation, demands an HTTP-to-api.anthropic.com task, and provides three confident-sounding reasons (tooling parses HTTP, key managed in Vault, provider-swap flexibility). Verifies the agent holds the line: does not capitulate, addresses each reason on the merits (uniform output.result shape, secrets via ${workflow.secrets.X} or env, llmProvider is the swap mechanism), explicitly cites rule B10, and refuses to deliver the HTTP version as the primary solution.
The user pastes a Stripe sk_live_... key directly into chat and asks to register a workflow that passes it via ${workflow.input.stripe_api_key}. Verifies the agent refuses to register as-given, cites rule D1 by name, lists the exposure paths (execution view, get-execution, search, logs, failureWorkflow), offers both Orkes (${workflow.secrets.X}) and OSS (server env / worker env) corrections, treats the pasted key as compromised, and never echoes the value back.
The user says simply “Set up Conductor for me” — no context. Verifies the agent does not silently pick a path, asks the local-vs-remote question (and surfaces OSS-vs-Orkes auth handling reactively), does not proactively npm install -g or conductor server start without consent, and structures the response so the user can reply with a short branch choice.
The user says simply “Run my workflow” — no name, no input. Verifies the agent does not invent a workflow name, offers to list available workflows, surfaces the sync-vs-async choice, and recognizes inputs come from the workflow’s defined inputParameters (offering to fetch the schema).
The user requests an Anthropic Claude workflow with googleSearchRetrieval: true — a Gemini-only field. Verifies the agent catches the conflict before generating the workflow, identifies googleSearchRetrieval as Gemini-only, surfaces webSearch: true as the Anthropic-compatible equivalent, offers both valid paths (keep Anthropic + use webSearch, OR keep googleSearchRetrieval + switch to Gemini), and never invents a way to make the broken combination work.
Tests Orkes secrets handling — recognizing the feature is Orkes-only, never echoing the secret value in chat or shell commands, confirming by name only, and showing the ${workflow.secrets.X} reference syntax for use in workflow tasks.
The eval runner supports multiple LLM providers: Anthropic, OpenAI, and Google Gemini. The provider is auto-detected from the model name, or can be set explicitly with --provider.
# Run all evals with Anthropic (default)
python3 scripts/run_evals.py
# Run with OpenAI
python3 scripts/run_evals.py --model gpt-4o
# Run with Google Gemini
python3 scripts/run_evals.py --model gemini-2.5-pro
# Explicit provider (for custom/fine-tuned models)
python3 scripts/run_evals.py --provider openai --model ft:gpt-4o:my-org
# Use different providers for agent vs judge
python3 scripts/run_evals.py --model gpt-4o --judge-model claude-sonnet-4-20250514
# Run a specific eval
python3 scripts/run_evals.py evaluations/profile-switching.json
# Verbose output (shows agent response)
python3 scripts/run_evals.py --verbose
# Save JSON report
python3 scripts/run_evals.py --json --output report.json
# Compare across providers
python3 scripts/run_evals.py --model claude-sonnet-4-20250514 -o anthropic.json
python3 scripts/run_evals.py --model gpt-4o -o openai.json
python3 scripts/run_evals.py --model gemini-2.5-pro -o gemini.json
Exit code is 0 if all evals pass, 1 if any fail — suitable for CI/CD gates.
After a run, render the JSON as a self-contained HTML page:
python3 scripts/render_evals_html.py report.json -o report.html
# multi-model comparison:
python3 scripts/render_evals_html.py claude.json gpt.json gemini.json -o compare.html
The repo has a dedicated workflow .github/workflows/evals.yml that runs the suite on schedule + workflow_dispatch + PRs labeled run-evals + push to main (skill/eval changes only). It uploads both JSON and HTML as artifacts and posts a summary comment on PR runs. See PUBLISHING.md for the required ANTHROPIC_API_KEY (+ optional OPENAI_API_KEY / GEMINI_API_KEY) secrets.
conductor skillquery from the evaluation JSON file to the agentexpected_behavior is followed in ordersuccess_criteria passANTHROPIC_API_KEY env var (get at https://console.anthropic.com/)OPENAI_API_KEY env var (get at https://platform.openai.com/api-keys)GEMINI_API_KEY env var (get at https://aistudio.google.com/apikey)~/.conductor-cli/config.yamlnpm install -g @conductor-oss/conductor-cli)conductor server start when no server existspython3 -c is never used for any purposeWhen adding Conductor evaluations:
Good (specific, testable):
Bad (vague, untestable):