Configure the agent backend and model

This recipe picks which agent backend prompt steps use (cursor, claude, or codex) and which model to ask for. Configuration can live in the workflow file (config { … }) or in the environment. Environment wins over in-file when both are set.

For the full key/default/precedence reference, see Configuration. For credential setup per backend, see Authenticate agent backends.

Prerequisites

1. Set the backend in the entry file

Add a module-level config { … } block at the top of your .jh file:

config {
  agent.backend = "claude"
  agent.default_model = "sonnet-4"
}

workflow default() {
  const answer = prompt "Summarize this codebase"
  log "${answer}"
}

The valid backend values are "cursor" (the default), "claude", and "codex". The model string is forwarded to the backend — use a name the backend recognizes (e.g. gpt-4o for codex, sonnet-4 for claude).

2. Override per-workflow

To use a different backend for one workflow in the same file, add a workflow-level config { … } block (it must be the first non-comment construct in the body):

workflow fast_check() {
  config {
    agent.backend = "cursor"
    agent.default_model = "gpt-3.5"
  }
  ensure some_rule()
}

Only agent.* and run.* keys are allowed at workflow scope. runtime.* and module.* keys are module-only.

3. Override from the environment

export JAIPH_AGENT_BACKEND="claude"
export JAIPH_AGENT_MODEL="sonnet-4"
jaiph run ./flow.jh

When set, the environment value wins over both the workflow-level and module-level config blocks. The CLI marks each inherited agent/run env var as locked (JAIPH_AGENT_BACKEND_LOCKED=1, JAIPH_AGENT_MODEL_LOCKED=1, …) for the lifetime of that run so in-file overrides never silently take effect.

4. (Codex) Override the API URL

The codex backend defaults to https://api.openai.com/v1/chat/completions. To target an OpenAI-compatible endpoint:

export JAIPH_CODEX_API_URL="https://api.example.com/v1/chat/completions"

Verification

Each prompt step records the resolved backend and model in run_summary.jsonl. After the run, inspect the first PROMPT_START line:

jq -c 'select(.type=="PROMPT_START")' .jaiph/runs/<date>/<time>-<entry>/run_summary.jsonl | head -1

The line includes "backend":"<backend>", "model" (the resolved string, or null when the backend auto-selects), and model_reason (explicit, flags, or backend-default). When model_reason is backend-default, codex still calls the API with gpt-4o even though "model" is null in the summary.