lua drains.
lua drains manages the organization’s log drains: the rules that copy agent execution logs to a destination you own. Every action runs against the organization, not against one agent, and takes effect for the next flush.
Every verb needs a credential holding logs:manage on the organization, which organization admins and owners have. It is a sensitive scope: a wildcard grant does not satisfy it, so a scoped key must name it.
Log drains are switched on for a deployment as a whole, not per organization. While they are off, every verb answers
404 — the resource does not exist rather than being forbidden.Synopsis
Description
With no action the command lists the organization’s drains, exactly aslua drains list does — drains are an organization resource, so there is nothing to pick first. With an action it runs once and exits. Every verb supports --json.
--org <id> chooses the organization and is accepted by every verb. Without it the command uses the organization of the project in the current directory; outside a project directory it uses the credential’s organization when the credential reaches exactly one. A credential that reaches several organizations must pass --org, and the refusal lists the ids you can choose from.
list prints every drain in the organization. status adds health and quota; with an id it prints one drain in detail. It exits 2 when any drain is in state failing, and sets that code after printing, so --json still emits its full payload. deliveries prints recent delivery attempts for one drain, newest first.
create and update take the same flags; update leaves out --type, which cannot be changed after creation — delete the drain and create a new one instead. Changing --endpoint sends the drain back to pending_verification and stops delivery until you re-verify; records keep buffering while you do.
verify re-runs ownership verification. test sends one lua.drain.test record through the real delivery path and prints the status code, latency, and response excerpt. pause stops delivery but keeps buffering; resume returns the drain to degraded, never straight to healthy. delete is a soft delete: the destination’s credentials are purged and queued records are dropped.
Both test and verify post the request and then wait for its outcome, because the delivery itself happens on the platform: test waits up to 30 seconds for the delivery attempt to land, verify up to 60 seconds for the verification result. The wait is not the operation — the request is already enqueued when the wait starts — so when nothing has landed in time the command exits 1 and names the command that will show the outcome once it does: lua drains deliveries <id> --kind test after a test, lua drains status <id> after a verification. With --json the payload is still printed, with pending: true on it.
rotate-secret mints a new HMAC signing secret and prints it once. It opens a 24-hour window in which deliveries carry two signatures, so a receiver can be updated without dropping a batch; --finalize closes the window early. See Verify signatures.
Secrets are never flags
Header values and signing secrets never appear on a command line, where a shell history or a CI log would keep them.--header <name>names a header and the CLI prompts for its value, hidden as you type.--header-from-env <name>=<VAR>reads the value from the named environment variable instead. This is the form for--ci, where prompting is not possible.- The HMAC signing secret is not an input at all. The platform mints it and prints it once, on
createand onrotate-secret.
list, status, or the REST API — carries header names and the last four characters of each value, never a value.
Content acknowledgement
--include-content turns on the user_message and agent_response sources, which carry what end users said and what the agent replied. The flag prints an acknowledgement and then requires a confirmation; --yes gives that confirmation non-interactively. Without either, the command prints the acknowledgement and exits non-zero without creating anything.
lua drains update <id> --no-include-content turns content off again. It leaves --sources exactly as they are: user_message and agent_response stay selected and their records keep arriving, with the body withheld and lua.content.withheld set — so you still see that a turn happened, on what channel and for which end user, without the words. Drop the sources too if you want the records gone. Turning content off and naming a content source in the same update is refused: send the sources first, then --no-include-content.
Arguments
Options
Output
list prints a box-drawn table:
Output
… — a drain name here, a pause reason or a response excerpt elsewhere. --json is never abridged, so read it rather than the table whenever a full value matters.
--json returns the drains exactly as the API models them, with header values and the signing secret absent:
lua drains list --json
status --json returns the same drains trimmed to what an operator watches:
lua drains status --json
create --json is the only place the signing secret appears. It is present for http drains, which are signed, and absent for the others:
lua drains create --json
test --json reports the round trip:
lua drains test --json
"ok": false, "pending": true, and null for the fields the attempt would have filled.
deliveries --json returns { deliveries, nextCursor }, one entry per attempt, with the status code, latency, byte counts, error class, and a scrubbed response excerpt — never the request body.
Examples
Create a Datadog drain in CI, reading the API key from the environment:status sets exit code 2 for this after it has printed, so --json still emits its payload — but 2 is also the usage exit code, so a guard that has to tell the two apart reads state from that payload:
Errors
A4xx with a code prints <code>: <message>, plus the offending field when the server names one.
A
403 prints:
Exit codes
See also
- Ship logs to your stack — what a drain is, and what it selects
- Delivery guarantees — retry, drops, heartbeat, and the health states behind
status - Verify signatures — what
rotate-secretchanges on the wire - Log drains REST — the same operations over HTTP
lua logs— reading the same records from the platform’s own copy

