Repository navigation
Name the cron job on the model requests of its sessions - #662
alex-clickhouse wants to merge 2 commits into
Conversation
In external mode, a proxy in front of the model API can attribute model usage by person and by trigger, but not by cron job. Scheduled work is a large part of an agent's model usage, so the cost of each job must be visible. The model requests of a session that a cron job started now carry one X-Nerve-Inference-Cron-Job header with the job, through ANTHROPIC_CUSTOM_HEADERS, under the same rules as the principal and trigger headers. Job IDs are free text, so Nerve changes the ID to 1 to 64 bytes of ASCII letters, digits, '.', '_' and '-', with a short hash when the ID has no such character or is too long. The leg session of a workflow run that a cron job started records the job in its origin, so its requests name the job too. The origin link of such a session opens the workflow runs, as for other workflow legs. Nerve's own model calls, Run later sessions and Codex send no cron job header. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@copilot resolve the merge conflicts in this pull request |
…ob-header # Conflicts: # docs/config.md # nerve/agent/backends/base.py # nerve/agent/backends/claude.py # nerve/agent/engine.py # nerve/inference_principal.py # tests/test_inference_principal.py Co-authored-by: alex-clickhouse <237136924+alex-clickhouse@users.noreply.github.com>
Resolved and merged |
|
Nerve PR review · ⏸ Hold: mostly a duplicate of #658, needs a decision Since #658 merged, every isolated and persistent cron session already sends Completeness: tests cover the transform, the CLI env, and cron, persistent and workflow sessions. The docs are in Before merge:
Checked: 397 tests passed in an offline sandbox at |
|
Closed: #658 (merged) covers this change. Nerve sends the cron job in |
What
In external mode, each model request of a session that a cron job started carries one
X-Nerve-Inference-Cron-Jobheader. The value names the job. This covers isolated and persistent cron jobs, and the leg session of a workflow run that a cron job started.How
nerve/inference_principal.pyadds the header next toX-Nerve-Inference-PrincipalandX-Nerve-Inference-Trigger, with the same rules: local mode sends none, Nerve removes an inherited line fromANTHROPIC_CUSTOM_HEADERS, and a CLI process keeps the value for its whole life. The engine reads the job from the session'sorigin_detail.cron_joband gives it to the Claude backend inSessionSpec.inference_cron_job.cron_job_tag_value()changes an ID to 1 to 64 bytes of ASCII letters, digits,.,_and-: each run of other characters becomes-, and-at the ends is removed. An empty result becomesjob-<8 hex of SHA-256>, and a result over 64 bytes becomes its first 55 bytes,-and the hash. So every job gets a value, and two IDs give the same value only rarely.created_bycron:<job>records the job inorigin_detail. Its origin line reads "From cron job ", and its origin link still opens the workflow runs:originLinkchecksworkflow_runbeforecron_job.Why
A proxy in front of the model API can attribute model usage by person and by trigger, but not by cron job. Scheduled work is a large part of an agent's model usage, so the cost of each job must be visible.
Testing
.venv/bin/pytest tests/(6 parts, temporary HOME): 8686 passed, 39 skipped, total equal to the 8725 collectedcd web && npm run build && npm test: build clean, 1892 tests passed🤖 Generated with Claude Code