pulse api compose
Audience: CLI users executing a batch of related requests in one call.
pulse api compose runs multiple types.Request
entries against one or more cohorts. The whole batch is one
ComposedRequest; the engine can run the entries sequentially or in
parallel against a bounded worker pool.
LLM agents using MCP: see the
pulse_composeMCP tool and thecompose-requestsskill.
Synopsis
pulse api compose --request FILE [--json] [--stream]
[--parallel N] [--no-fail-fast]
[--no-defaults]
Flags
| Flag | Alias | Type | Default | Purpose |
|---|---|---|---|---|
--request | -r | string | (required) | Composed-request JSON path |
--json | bool | false | Wrap output in the standard envelope | |
--stream | bool | false | Stream rows as NDJSON; each line is {"index": N, "row": {...}} | |
--parallel | int | 1 | Worker count; 0 = GOMAXPROCS, 1 = sequential | |
--no-fail-fast | bool | false | Aggregate errors across slots instead of cancelling on first failure (parallel mode only) | |
--no-defaults | bool | false | Disable smart operator-type inference |
Request file shape
{
"requests": [
{ "cohort": {"filename": "sales.pulse"}, "aggregations": [...] },
{ "cohort": {"filename": "sales.pulse"}, "groups": [...] },
{ "cohort": {"filename": "ops.pulse"}, "filterers": [...] }
]
}
Each requests[i] is a full types.Request. Slots are independent —
they may target different cohorts, use different operators, etc.
Output ordering
Responses come back in input order, regardless of --parallel.
A worker that finishes early waits its turn before emitting. So
responses[i] always corresponds to request.requests[i].
Parallel mode
--parallel N:
1(default) — sequentialCompose, equivalent to running each request throughpulse api processin a loop.0—runtime.GOMAXPROCSworkers.>1— exactly N workers.
Workers share Pulse’s read-only registries; per-request stateful operators are constructed fresh. See Parallel Compose for full mechanics.
FailFast semantics
With --no-fail-fast unset (the default, fail-fast on):
- The first failing request cancels in-flight siblings.
- The command exits non-zero with the first error.
With --no-fail-fast:
- Every request runs to its own completion (or per-request timeout).
- Errors aggregate into a single
SERVICE_INTERNALerror whosedetails.failed_indiceslists the slot indices that failed. - Successful slots populate the response array; failed slots are
null.
Output
--json
{
"format_version": "1.0",
"data": [ /* response per slot, in input order */ ],
"errors": [],
"warnings": []
}
--stream
{"index": 0, "row": { ... }}
{"index": 0, "row": { ... }}
{"index": 1, "row": { ... }}
The index field identifies which slot’s request produced each row.
Exit codes
| Code | Meaning |
|---|---|
| 0 | All requests succeeded |
| 1 | One or more requests failed (fail-fast: first error; aggregated: any failure) |
Examples
Sequential batch
pulse api compose --request batch.json --json
Parallel with 4 workers, aggregated errors
pulse api compose --request batch.json --parallel 4 --no-fail-fast --json
Stream a parallel batch into a downstream consumer
pulse api compose --request batch.json --parallel 4 --stream | \
jq -c 'select(.index == 2)'
Related
pulse api process— single-request leaf- Library: Parallel Compose — Go-side equivalents
skills/compose-requests.md(LLM) — request composition patterns