Skip to main content
Verified against lua-cli 3.38.0, the first release carrying 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 as lua 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 create and on rotate-secret.
A drain read back — by 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
Every table the command prints is fitted to 100 columns, and a value too long for its column is clipped with an — 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
When the 30-second wait passes with nothing recorded, the same payload carries "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:
Create a signed HTTPS drain, save the secret, and verify the endpoint:
Fail a CI step when any drain is failing. 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:
Look at why a drain is unhappy:
Narrow a noisy drain to errors on one agent:
Pause during a receiver deploy, then resume. Records buffer while it is paused:
Rotate the signing secret with no delivery gap:

Errors

A 4xx with a code prints <code>: <message>, plus the offending field when the server names one. A 403 prints:

Exit codes

See also