* feat(claude_code_exec): add claude code optimizer backend with SDK trace support Register claude_code_exec as a full optimizer/target backend (issue #233). --backend claude_code_exec now defaults both roles to claude_code_exec so reflection sees the agent's complete session, and the SDK message stream is parsed into structured trace steps persisted as claude_trace_steps.txt and injected into the analyst prompt. - model/claude_code_backend.py (new): chat_optimizer/chat_optimizer_messages on run_claude_code_chat, reasoning_effort threaded through, retry loop that surfaces non-JSON structured replies as RuntimeError, token tracking. - model/codex_harness.py: parse/format/persist claude trace steps (text, tool_call, tool_result; drops init/thinking_tokens; 200-char tool_result cap; total truncation) + effort override on run_claude_code_chat. - trainer.py/reflect.py: inject Claude Trace Steps gated behind REFLACT_CLAUDE_TRACE_TO_OPTIMIZER, set by the trainer only for claude_code_exec targets with model.claude_trace_to_optimizer (mirrors codex gate; default true). - config.py/default.yaml/docs: model.claude_trace_to_optimizer key + flatten mapping + config.md rows. - backend_config.py + model/__init__.py: register backend, route chat dispatch, token summary, reasoning effort, deployments. - scripts/train.py, eval_only.py: symmetric default + accurate comments. - tests: tests/test_claude_code_backend.py (10 tests: parsing, dispatch, effort, retry, trainer/reflect gating); test_role_backend_resolution.py updated to the symmetric default. Verified: 58 unit tests pass; integration smoke on searchqa improved best-on-val 0.7500 -> 0.9375 with 80 claude_trace_steps.txt written; all output files valid UTF-8 (no GBK mojibake). * fix(claude_code_exec): address #233 review feedback
14 KiB
Configuration Reference
SkillOpt loads structured YAML, resolves _base_ inheritance, and flattens
the result for the trainer. Shipped defaults live in
configs/_base_/default.yaml; benchmark configs override them.
Model and Backend Selection
Use explicit optimizer and target backends when the two roles differ or when selecting the generic OpenAI-compatible backend.
| Backend | Optimizer | Target |
|---|---|---|
openai_chat |
✓ | ✓ |
openai_compatible |
✓ | ✓ |
claude_chat |
✓ | ✓ |
qwen_chat |
✓ | ✓ |
minimax_chat |
✓ | ✓ |
copilot_chat |
✓ | ✓ |
codex_exec |
✓ | ✓ |
claude_code_exec |
— | ✓ |
cursor_exec |
— | ✓ |
copilot_exec |
— | ✓ |
MiniMax currently has one shared deployment. model.minimax_model is applied
when MiniMax is the target; mixed-backend runs cannot independently choose a
MiniMax optimizer model and a different target model.
model.minimax_region selects the service region: global_en (default)
resolves to https://api.minimax.io/v1 and cn_zh resolves to
https://api.minimaxi.com/v1. model.minimax_base_url overrides it.
| Parameter | Type | Default | Description |
|---|---|---|---|
model.backend |
str | azure_openai |
Backward-compatible high-level run label |
model.optimizer |
str | gpt-5.5 |
Optimizer deployment/model |
model.target |
str | gpt-5.5 |
Target deployment/model |
model.optimizer_backend |
str | openai_chat |
Optimizer client path; chat backends plus codex_exec |
model.target_backend |
str | openai_chat |
Target client path; chat or exec backend |
model.reasoning_effort |
str | medium |
Shared reasoning effort |
model.rewrite_reasoning_effort |
str | empty | Optional full-rewrite effort override |
model.rewrite_max_completion_tokens |
int | 64000 |
Full-rewrite output cap |
Azure/OpenAI openai_chat
| Parameter | Default | Description |
|---|---|---|
model.azure_openai_endpoint |
empty | Shared Azure resource URL or compatibility-mode base URL |
model.azure_openai_api_version |
2024-12-01-preview |
Azure API version |
model.azure_openai_api_key |
empty | Key for api_key or compatibility auth |
model.azure_openai_auth_mode |
empty | Config value; empty falls back to env, whose default is azure_cli |
model.azure_openai_ad_scope |
Azure Cognitive Services scope | AAD token scope |
model.azure_openai_managed_identity_client_id |
empty | Optional user-assigned identity client ID |
Every shared key also has an optimizer_azure_openai_* and
target_azure_openai_* form.
Claude claude_chat
claude_chat launches an installed, authenticated Claude Code CLI with
claude -p; it does not instantiate an Anthropic API client. The executable
defaults to claude and can be overridden with CLAUDE_CLI_BIN.
ANTHROPIC_API_KEY is one authentication option understood by the CLI.
Qwen thinking mode
qwen_chat speaks the OpenAI chat-completions protocol, so it reaches both
self-hosted servers (vLLM, SGLang) and hosted OpenAI-compatible gateways.
chat_template_kwargs is a vLLM/SGLang extension: OpenAI, Azure OpenAI, and
strict gateways reject the unknown body field with HTTP 400, and non-Qwen vLLM
models served with it may emit <think> output without an <answer> tag.
Because the correct wire policy therefore depends on the serving stack rather
than on a boolean preference, it is an explicit three-state setting:
thinking_mode |
On the wire |
|---|---|
server_default (default) |
chat_template_kwargs is not sent; the server's chat template decides |
enabled |
sends chat_template_kwargs: {"enable_thinking": true} |
disabled |
sends chat_template_kwargs: {"enable_thinking": false} |
server_default is the portable default and works against any
OpenAI-compatible endpoint, but Qwen3 chat templates enable thinking by
default, so the outcome depends on the serving stack and template version. The
backend warns once per role when a request is sent under server_default. For
reproducible runs pin enabled or disabled; the resolved per-role mode is
recorded in the run's config.json under resolved_qwen_thinking_modes.
The legacy model.qwen_chat_enable_thinking boolean keeps its historical
meaning exactly — true sends enable_thinking: true, false omits the field
(it never sent an explicit false) — so existing configs are unaffected.
Setting both keys to conflicting values raises an error rather than picking a
winner. Prefer thinking_mode; use disabled when you need the field sent.
Qwen, MiniMax, and Exec Backends
| Parameter family | Description |
|---|---|
model.qwen_chat_* |
Shared base_url, api_key, temperature, timeout_seconds, max_tokens, thinking_mode, and the legacy enable_thinking |
model.qwen_chat_thinking_mode |
Wire policy for chat_template_kwargs.enable_thinking: server_default (default; omit the field), enabled, or disabled. See Qwen thinking mode |
model.optimizer_qwen_chat_* / model.target_qwen_chat_* |
Per-role Qwen overrides, including *_qwen_chat_thinking_mode |
model.minimax_* |
MiniMax region, base_url, api_key, shared minimax_model, temperature, max_tokens, and enable_thinking; minimax_model applies when MiniMax is the target |
model.codex_exec_* |
Codex path, sandbox, profile, SDK mode, reasoning, network/search, and approval policy; see compatibility notes below |
model.claude_code_exec_* |
Claude path, profile, SDK mode, effort, and thinking-token cap |
model.codex_trace_to_optimizer |
When true (default) and target is codex_exec, inject the agent's codex trace steps into the reflection prompt |
model.claude_trace_to_optimizer |
When true (default) and target is claude_code_exec, inject the agent's claude trace steps into the reflection prompt |
model.cursor_exec_path |
Cursor Agent executable path; default cursor-agent |
model.cursor_exec_sandbox |
Cursor sandbox mode: enabled (default) or disabled; file-edit rollouts require enabled |
model.copilot_exec_path |
GitHub Copilot CLI executable path; default copilot |
model.copilot_exec_home |
Optional COPILOT_HOME override isolating CLI config |
model.copilot_exec_allow_all_tools |
Optional opt-in to --allow-all-tools; unset by default so COPILOT_EXEC_ALLOW_ALL_TOOLS remains authoritative |
model.copilot_chat_optimizer_model / model.copilot_chat_target_model |
Optional per-role --model IDs for copilot_chat |
model.copilot_chat_timeout |
Per-call timeout in seconds for copilot_chat |
For compatibility, model.codex_bin, model.codex_cli_bin, and
model.codex_path are aliases for model.codex_exec_path;
model.codex_sandbox and model.sandbox are aliases for
model.codex_exec_sandbox. The canonical codex_exec_* name wins when both
forms occur in the same YAML layer. A child config or command-line override
still overrides its base config, whichever accepted spelling it uses.
The aliases may also be supplied without the model. prefix through
--cfg-options; with a structured config they are applied to the model
section.
model.codex_exec_full_auto and --codex_exec_full_auto remain accepted for
backward compatibility but are deprecated and ignored. Set
model.codex_exec_sandbox and model.codex_exec_approval_policy explicitly.
Blank or null Codex values in the shipped base config leave the corresponding
CODEX_EXEC_* environment variable in control. The effective precedence is an
explicit command-line/YAML value, then the environment, then the built-in safe
default (codex, workspace-write, and approval policy never).
model.codex_exec_network_access controls outbound network access only while
the Codex sandbox is workspace-write; it cannot restrict
danger-full-access. model.codex_exec_web_search independently selects live
web search when true and disables web search when false. These settings are
forwarded consistently to both SDK and CLI execution paths.
Warning
danger-full-accessgrants the Codex process unrestricted filesystem access. Use it only in an appropriately isolated environment, such as a disposable container. The same warning applies to environment aliases such asCODEX_SANDBOX_MODE=danger-full-access.
Training (train)
| Parameter | Type | Default | Description |
|---|---|---|---|
train.num_epochs |
int | 4 |
Training epochs |
train.train_size |
int | 0 |
0 derives the size from the dataset split |
train.steps_per_epoch |
int | derived | Runtime field recomputed from train size, batch size, and accumulation; configured values are overwritten |
train.batch_size |
int | 40 |
Tasks sampled per step |
train.accumulation |
int | 1 |
Accumulation rounds per step |
train.seed |
int | 42 |
Random seed |
Gradient / Reflection (gradient)
| Parameter | Type | Default | Description |
|---|---|---|---|
gradient.minibatch_size |
int | 8 |
Reflect minibatch size |
gradient.merge_batch_size |
int | 8 |
Patch merge batch size |
gradient.analyst_workers |
int | 16 |
Parallel reflection workers |
gradient.failure_only |
bool | false |
Reflect only on failures |
Optimizer (optimizer)
| Parameter | Type | Default | Description |
|---|---|---|---|
optimizer.learning_rate |
int | 4 |
Maximum edit patches per step |
optimizer.min_learning_rate |
int | 2 |
Floor for decaying schedules |
optimizer.lr_scheduler |
str | cosine |
constant, linear, cosine, or autonomous |
optimizer.lr_control_mode |
str | fixed |
fixed, autonomous, or none |
optimizer.skill_update_mode |
str | patch |
patch, rewrite_from_suggestions, or full_rewrite_minibatch |
optimizer.use_slow_update |
bool | true |
Epoch-boundary longitudinal update |
optimizer.slow_update_samples |
int | 20 |
Longitudinal evaluation samples |
optimizer.slow_update_gate_with_selection |
bool | false |
Gate slow-update guidance on the selection split |
optimizer.longitudinal_pair_policy |
str | mixed |
mixed, changed, or unchanged |
optimizer.use_meta_skill |
bool | true |
Cross-epoch optimizer memory |
optimizer.use_skill_aware_reflection |
bool | false |
Enable skill-defect vs execution-lapse routing |
optimizer.skill_aware_appendix_source |
str | both |
both or failure_only |
optimizer.skill_aware_consolidate_threshold |
int | 0 |
Appendix compaction threshold; 0 disables it |
Evaluation (evaluation)
| Parameter | Type | Default | Description |
|---|---|---|---|
evaluation.use_gate |
bool | true |
Accept only improvements when enabled; false records validation but force-accepts each candidate |
evaluation.gate_metric |
str | hard |
hard, soft, or mixed |
evaluation.gate_mixed_weight |
float | 0.5 |
Soft-score weight for mixed |
evaluation.use_semantic_density |
bool | false |
Add the optional instruction-density bonus |
evaluation.semantic_density_weight |
float | 0.05 |
Density bonus weight |
evaluation.leading_words |
list/str | built in | Optional custom high-influence words |
evaluation.sel_env_num |
int | 0 |
Selection size; 0 uses the full split |
evaluation.test_env_num |
int | 0 |
Test size; 0 uses the full split |
evaluation.eval_test |
bool | true |
Run final test evaluation |
Environment (env)
| Parameter | Type | Default | Description |
|---|---|---|---|
env.name |
str | empty | Benchmark name |
env.skill_init |
str | empty | Initial skill document |
env.split_mode |
str | ratio |
ratio or split_dir |
env.split_ratio |
str | benchmark/default | Train:validation:test ratio |
env.split_seed |
int | 42 |
Deterministic split seed |
env.split_dir |
str | empty | Materialized train/val/test directory |
env.data_path |
str | empty | Raw data path for ratio mode |
env.split_output_dir |
str | empty | Optional materialized split output |
env.exec_timeout |
int | 120 |
Per-task timeout in seconds |
env.out_root |
str | generated by the train/eval CLIs | Output directory |
Benchmark-specific env keys are passed through to the adapter.
Credential Environment Variables
Azure-family backend
| Variable | Description |
|---|---|
AZURE_OPENAI_ENDPOINT |
Shared Azure endpoint or compatibility base URL |
AZURE_OPENAI_API_VERSION |
Azure API version |
AZURE_OPENAI_AUTH_MODE |
api_key, azure_cli, managed_identity, or openai_compatible |
AZURE_OPENAI_API_KEY |
Key for api_key or openai_compatible mode |
AZURE_OPENAI_AD_SCOPE |
Optional AAD scope |
AZURE_OPENAI_MANAGED_IDENTITY_CLIENT_ID |
Optional managed-identity client ID |
Use OPTIMIZER_AZURE_OPENAI_* and TARGET_AZURE_OPENAI_* for role-specific
overrides.
Generic OpenAI-compatible backend
| Variable suffix | Shared / per-role forms |
|---|---|
BASE_URL |
OPENAI_COMPATIBLE_BASE_URL, OPTIMIZER_OPENAI_COMPATIBLE_BASE_URL, TARGET_OPENAI_COMPATIBLE_BASE_URL |
API_KEY |
Corresponding shared/optimizer/target *_API_KEY names |
MODEL |
Corresponding shared/optimizer/target *_MODEL names |
TEMPERATURE |
Corresponding shared/optimizer/target *_TEMPERATURE names |
MAX_TOKENS |
Corresponding shared/optimizer/target *_MAX_TOKENS names |
TIMEOUT_SECONDS |
Corresponding shared/optimizer/target *_TIMEOUT_SECONDS names |
The train/eval entry points set deployments from YAML model.optimizer and
model.target after backend initialization. For selected OpenAI-compatible or
Qwen roles, those values override the corresponding *_MODEL environment
variables; the environment model names mainly seed direct library use.
Other backend families use the authenticated Claude CLI (CLAUDE_CLI_BIN;
optionally ANTHROPIC_API_KEY), QWEN_CHAT_*, and MINIMAX_*.
SkillOpt-Sleep's compatible endpoint uses AZURE_OPENAI_*, not the research
backend's OPENAI_COMPATIBLE_*; see
the Sleep endpoint guide.