wait_for_job
Block until a job is terminal, then return it. Free, bounded, no poll loop.
Returns the chosen get_job result_view plus timed_out, waited_ms and polls; branch on
`status` exactly as you would with get_job. timed_out:true is NOT a failure, it
means the budget ran out: call again with the SAME job_id. Waiting neither cancels
nor charges; the worker charges when it runs the job either way. It returns
IMMEDIATELY with worker_alive:false + `warning` when no worker exists here.
Errors: unauthorized, not_found (unknown or foreign job_id), rate_limited.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes | The job to wait on, as returned by start_generate_job (or by a generate_hooks call that auto-jobbed on deadline_ms). Account-scoped: an id you do not own reads as not_found. | |
| api_key | No | API key for this call. Omit to fall back to the Authorization: Bearer / X-API-Key request header (streamable-HTTP only), then the VHGENGINE_API_KEY env var (the stdio default). No key resolvable -> unauthorized. | |
| result_view | No | Use compact for source evidence and costs with less response text. Full preserves every audit receipt. Views never rerun or recharge research. | full |
| timeout_seconds | No | How long to block, 1-300 seconds. Keep it BELOW your own MCP client's request timeout, or the client gives up before this tool answers. Running out is not an error: you get timed_out:true plus the job's live state. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| error | No | On failure: the same typed error envelope a synchronous call returns. details.cancelled true means YOU cancelled it with cancel_job, not a fault. | |
| polls | No | How many get_job reads this call made on your behalf. | |
| stage | No | The real engine stage reached (e.g. brief, draft, judge). | |
| job_id | No | The job waited on. | |
| result | No | On success: the FULL generate (or batch) body, always full-verbosity. At standard/full, a judge-ranked smart hook may also carry {shape, phone_test, say_it}; a judge-ranked research hook carries receipts {persona, shape, phone_test, say_it, pattern_source}. pattern_source is null when no measured opener was attributed, otherwise its nested provenance is the authoritative actual platform, source surface, transcript method, language, route, media, and origin-time record. Minimal keeps persona and shape, plus phone_test only when it is the warning value 'fail'. result_view=compact projects V1 research to source evidence, citations, limitations, cost and an execution summary. Full is the compatible default; changing views never executes research again. Other job types retain their existing body. | |
| status | No | queued, running, succeeded (see `result`) or failed (see `error`). With timed_out:false this is always succeeded or failed unless worker_alive is false. | |
| warning | No | Present only alongside worker_alive:false; says what to do instead. | |
| timed_out | No | true when timeout_seconds elapsed before the job finished. NOT a failure: call wait_for_job again with the SAME job_id, or poll get_job. | |
| waited_ms | No | How long this call actually blocked. | |
| elapsed_ms | No | Milliseconds since the job started running. | |
| eta_seconds | No | Estimated seconds still remaining. | |
| progress_pct | No | 0-100 progress within the run. | |
| worker_alive | No | Present and FALSE only when the wait returned immediately because no job worker will ever run this job. Then read `warning`. | |
| hook_instances | No | Immutable non-prose served-occurrence identities. Profile-bound queued/running work returns an empty list; a successful result returns one row per served hook. | |
| poll_after_seconds | No | How long to wait before polling again; 0 once finished. | |
| resolved_creator_profile | No | Exact immutable creator-profile binding used by this occurrence. Null/absent for inline or unprofiled generation. |