Gateway API
The defenseclaw-gateway sidecar API — its registered route patterns, authentication and CSRF model, and inspection verdict shape. The handler code is authoritative.
defenseclaw-gateway exposes a sidecar management API used by hook scripts,
connector plugins, the CLI, and the TUI. This page lists every static route
pattern registered by APIServer.Run, the two provider routes installed by
registerProviderRoutes, and every built-in connector hook route.
This is not an OpenAPI specification. The canonical request and response
shapes are the handlers in
internal/gateway/api.go
and the files referenced from its mux.HandleFunc registrations.
This page covers the sidecar API on gateway.api_port. The separate guardrail
proxy listener on guardrail.port has its own OpenAI-compatible and provider
routes in internal/gateway/proxy.go.
Bind address
| Knob | Config default | Effective value |
|---|---|---|
gateway.api_port | 18970 | Sidecar API port |
gateway.api_bind | empty | 127.0.0.1 when empty, except for the standalone OpenShell rule below |
The API binds to loopback by default. In standalone OpenShell mode only, an
empty gateway.api_bind inherits guardrail.host when that value is non-empty
and is not the literal localhost; set gateway.api_bind: 127.0.0.1
explicitly when the management API must remain loopback-only. A non-loopback
value expands access to the authenticated management surface; protect that
listener with host firewalling and a deployment-specific network design.
gateway.host and gateway.port describe the upstream agent gateway, while
guardrail.host/guardrail.port control the separate guardrail proxy
listener.
Auth
Every request except GET /health must authenticate. The shared authentication
middleware accepts these header forms; all three are constant-time compared
with the resolved gateway token:
Authorization: Bearer <token>
X-DefenseClaw-Token: <token>
X-DC-Auth: Bearer <token>PATCH /v1/guardrail/config performs a second, endpoint-local check and accepts
only Authorization: Bearer or X-DefenseClaw-Token; X-DC-Auth alone is
rejected there. The endpoint also rejects every patch in
managed_enterprise deployment mode.
Loopback connector hook routes can instead use the matching connector's narrow
hook token. The Codex token also authorizes /api/v1/codex/notify. A
connector-scoped token on a generic /api/v1/inspect/* route is accepted only
over loopback and only when X-DefenseClaw-Connector names the same registered
connector.
OTLP credentials are source-specific only for the closed scope set
geminicli, codex, and claudecode. Codex and Claude Code send their scoped
bearer to /v1/{logs,metrics,traces} together with
X-DefenseClaw-Source: codex|claudecode; that header selects and must match the
scoped credential. Gemini CLI uses
/otlp/geminicli/{token}/v1/{signal} because its exporter cannot add the
authorization header. Once a scoped token exists for one of those sources, the
master gateway token is rejected for that source's scoped route. Other native
OTLP sources, including Copilot and OmniGent, currently authenticate their
loopback /v1/{signal} requests with the master gateway token.
The token is resolved from one of, in priority order:
- The env var named by
gateway.token_env(custom name — operator intent wins) DEFENSECLAW_GATEWAY_TOKEN(canonical)OPENCLAW_GATEWAY_TOKEN(legacy fallback for existing installs)gateway.tokendirectly in~/.defenseclaw/config.yaml
There is no standalone ~/.defenseclaw/gateway-token file. On first boot
the sidecar creates DEFENSECLAW_GATEWAY_TOKEN in
~/.defenseclaw/.env when neither a supported environment nor dotenv source
already supplies a token. Rotate a locally managed token with
defenseclaw setup rotate-token --yes; that transaction restarts the gateway
and refreshes active connector credentials. An externally managed custom
gateway.token_env must be rotated by its owning secret system.
CSRF protection
Every non-GET/HEAD request also requires X-DefenseClaw-Client (any
non-empty caller identifier such as cli, openclaw-plugin, or
inspect-hook/1.0). POST, PUT, PATCH, and DELETE requests require
Content-Type: application/json; OTLP requests instead require
application/json or application/x-protobuf. OPTIONS requires the client
header but no content type. The only narrow client-header exception is a
loopback scoped-token OTLP path, because some native exporters cannot add
arbitrary headers; that path still requires an OTLP content type and rejects a
non-local browser origin.
All ordinary mutations also reject a non-local Origin; cross-site requests
are rejected when Sec-Fetch-Site identifies them. A shared middleware caps
ordinary POST, PUT, and PATCH bodies at 1 MiB. Exact authenticated OTLP-HTTP
ingest routes use a separate 64 MiB receiver limit so exporter batches can
follow the protocol's recommended bound without increasing the limit for the
rest of the API.
X-DefenseClaw-Client: cliEndpoints
Health & status
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /health | exempt | Liveness + uptime + version. Used by k8s probes and defenseclaw doctor. |
GET | /status | required | Health, process identity, provenance, an optional connected-gateway hello, legacy singular connector_mode, and connector_modes (one entry per active connector). Used by defenseclaw status and the TUI. |
GET | /v1/connectors | required | Lists every connector registered in the gateway (name, description, source, hook capabilities, tool inspection mode). |
GET /status carries both a singular and a plural connector field so old and new clients keep working on a multi-connector install:
{
"connector_mode": {
"connector": "codex",
"mode": "observability",
"policy_mode": "action",
"guardrail_mode": "action",
"hook_fail_mode": "closed",
"enabled": true,
"hook_enforcement": true,
"enforcement_surface": "agent_lifecycle_hooks",
"telemetry": ["hooks", "otel", "notify"],
"proxy_intercept": false
},
"connector_modes": [
{
"connector": "codex",
"mode": "observability",
"policy_mode": "action",
"guardrail_mode": "action",
"hook_fail_mode": "closed",
"enabled": true,
"hook_enforcement": true,
"enforcement_surface": "agent_lifecycle_hooks",
"telemetry": ["hooks", "otel", "notify"],
"proxy_intercept": false
},
{
"connector": "claudecode",
"mode": "observability",
"policy_mode": "observe",
"guardrail_mode": "observe",
"hook_fail_mode": "closed",
"enabled": true,
"hook_enforcement": false,
"enforcement_surface": "agent_lifecycle_hooks",
"telemetry": ["hooks", "otel"],
"proxy_intercept": false
}
]
}connector_mode(singular) is the same summary object for the primary connector, retained for clients written before multi-connector existed. On a fan-out install it is not the authoritative roster view; useconnector_modesinstead.connector_modes(plural) is the authoritative per-connector view: one entry per active connector.modeis the backward-compatible data-path value (guardrailorobservability);policy_modeandguardrail_modereport the effectiveobserve/actionposture;hook_fail_modeis the effective hook fail mode;enabledis the connector's effective guardrail enablement;hook_enforcementis true for a non-proxy connector in action mode;enforcement_surfaceidentifies the proxy, lifecycle-hook, or OmniGent policy API path;telemetrylists reported wiring channels; andproxy_interceptis true only for proxy connectors.defenseclaw-gateway statusrenders its per-connector "Connector Mode" section directly from this array.
Connector hooks
Built-in connectors that implement the hook endpoint contract register the following routes. Proxy connectors such as OpenClaw and ZeptoClaw do not register a connector hook route.
| Method | Path | Connector | Source |
|---|---|---|---|
POST | /api/v1/claude-code/hook | Claude Code | internal/gateway/connector/claudecode.go |
POST | /api/v1/codex/hook | Codex | internal/gateway/connector/codex.go |
POST | /api/v1/cursor/hook | Cursor | internal/gateway/connector/hook_only.go |
POST | /api/v1/windsurf/hook | Windsurf | same |
POST | /api/v1/geminicli/hook | Gemini CLI | same |
POST | /api/v1/copilot/hook | GitHub Copilot CLI | same |
POST | /api/v1/openhands/hook | OpenHands | same |
POST | /api/v1/antigravity/hook | Antigravity | same |
POST | /api/v1/hermes/hook | Hermes | same |
POST | /api/v1/opencode/hook | OpenCode | same |
POST | /api/v1/amp/hook | Amp | internal/gateway/connector/amp.go |
POST | /api/v1/omnigent/hook | OmniGent | internal/gateway/connector/omnigent.go |
All hook endpoints share a per-IP rate limiter (20 RPS, burst 40 — see hookLimiter in api.go). Loopback callers (the on-host hook scripts) are exempt; the limit only applies to remote callers.
Inspection (rate-limited)
The /api/v1/inspect/* family is the hot path that connector hooks and the OpenClaw plugin call to score a single tool call, prompt, or completion. Mounted under a sub-mux that wraps the per-IP rate limiter.
| Method | Path | Used by | Purpose |
|---|---|---|---|
POST | /api/v1/inspect/tool | Shared hook script; OpenClaw extension | Inspect a tool call (tool + args), or inspect message content when tool: "message" supplies content and direction. Returns the verdict envelope below. |
POST | /api/v1/inspect/request | Shared hook script | Inspect an outbound LLM request (prompt). |
POST | /api/v1/inspect/response | Shared hook script | Inspect a model response. |
POST | /api/v1/inspect/tool-response | Shared hook script | Inspect a tool's output before it returns to the agent. |
/api/v1/inspect/tool is the existing trusted tool-call entry point; there is
no client-supplied is_tool_call switch and no additional semantic endpoint.
The authenticated route and its server-side connector identity establish the
boundary. A request with tool: "message" stays in the message lane and is not
eligible for structured tool-call CEL rules.
Single-call semantic findings are available on this inspect route and on
native pre-tool hooks. Ordered tool chains are stricter: they use durable
SQLite state only on authenticated /api/v1/{connector}/hook events with
canonical connector and session correlation. Inspect, proxy, router, and OTLP
traffic never advance a chain. Only a matching authoritative successful result
can promote an existing pending proposal into a durable successful predecessor.
A chain can deny only its final step on an enforcement-safe synchronous
pre-tool event. Post-tool and tool-result events never make the final blocking
decision.
See the stateful connector lifecycle for
the pairing, state-level, and cutoff contracts.
Chain matches are HIGH severity and retain the connector's effective action
matrix: default and permissive profiles alert, strict blocks, and eligible
human-in-the-loop configurations confirm. A durable deny receipt is created
only when that effective action is block.
| Ordered chain | Wall-clock window | Event horizon |
|---|---|---|
| Guardrails disabled → external egress | 30 minutes | 64 events |
| Permission denied → runtime bypass | 5 minutes | 16 events |
| Privilege discovery → elevation | 15 minutes | 32 events |
| Secret-manager read → external egress | 30 minutes | 64 events |
| Sensitive secret read → external egress | 30 minutes | 64 events |
| Workload identity access → lateral execution | 15 minutes | 32 events |
Chain state contains bounded masks and fingerprints rather than raw commands, arguments, paths, endpoints, or tool payloads. Durable deny receipts replay the same final decision without duplicating finding telemetry.
Code & network scanning
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/scan/code | Run the built-in CodeGuard scanner on the local filesystem path supplied in the JSON body. |
GET | /api/v1/network-egress | List persisted egress audit records. Supports limit, hostname, session_id, agent_id, root_agent_id, user_id, blocked, and RFC3339 since filters. |
POST | /api/v1/network-egress | Ingest one observed egress event into the audit logger; this is not an allow/block decision endpoint. |
Asset scanning
| Method | Path | Purpose |
|---|---|---|
POST | /v1/skill/scan | Run the skill scanner against the local target directory named in the request. |
POST | /v1/plugin/scan | Run the plugin scanner against the local target directory named in the request. |
POST | /v1/mcp/scan | Run the MCP scanner against a target URL or local path. |
POST | /v1/skill/fetch | Stream a tar.gz of an existing local directory after resolving it beneath a configured skill or plugin root; this does not fetch from a registry. |
POST | /scan/result | Persist a scanner result through the canonical audit logger. |
Asset enable / disable
| Method | Path | Purpose |
|---|---|---|
POST | /skill/disable | Ask the connected upstream agent gateway to disable a skill by key (skills.update). |
POST | /skill/enable | Ask the connected upstream agent gateway to enable a skill by key (skills.update). |
POST | /plugin/disable | Ask the connected upstream/OpenClaw gateway to disable a plugin through its config RPC. |
POST | /plugin/enable | Ask the connected upstream/OpenClaw gateway to enable a plugin through its config RPC. |
These routes return 503 when no upstream client object is present and 502
when an attempted upstream RPC fails, including a disconnected client. They do
not perform the CLI's filesystem quarantine/restore workflow.
Inventory
| Method | Path | Purpose |
|---|---|---|
GET | /skills | Return the connected upstream agent gateway's skills.status RPC payload. An absent client returns 503; an RPC/disconnection failure returns 502. |
GET | /mcps | Return MCP server entries for the singular active connector from DefenseClaw configuration; unavailable or malformed input returns an empty list. |
GET | /tools/catalog | Return the one connected upstream agent gateway's tools.catalog RPC payload. An absent client returns 503; an RPC/disconnection failure returns 502. |
Provider registry
| Method | Path | Purpose |
|---|---|---|
GET, HEAD | /v1/config/providers | Return the merged built-in and operator provider registry plus overlay status. |
POST | /v1/config/providers/reload | Reload the built-in registry and custom-providers.json overlay. |
Policy
| Method | Path | Purpose |
|---|---|---|
POST | /policy/evaluate | Debug the admission policy with {domain?: "admission", input: {target_type, target_name, path?, scan_result?}}. DefenseClaw injects its current allow/block lists and returns {ok: true, data: <AdmissionOutput>}; arbitrary OPA domains/input are rejected. |
POST | /policy/evaluate/firewall | Evaluate the firewall sub-policy in isolation. |
POST | /policy/evaluate/audit | Evaluate the audit sub-policy. |
POST | /policy/evaluate/skill-actions | Evaluate the skill_actions sub-policy by severity. |
POST | /policy/reload | Atomically reload .rego modules plus optional data.json from configured policy_dir (or its rego child), invalidate the judge cache, and return {"status":"reloaded","policy_dir":"..."}. |
Guardrail control plane
| Method | Path | Purpose |
|---|---|---|
POST | /v1/guardrail/event | Emit canonical telemetry for an already-decided guardrail event. Requires evaluation_id, direction (prompt or completion), action (allow, alert, or block), and severity (NONE through CRITICAL); latency/token values must be finite and nonnegative. Returns {"status":"ok"}. No production caller is wired in this repository. |
POST | /v1/guardrail/evaluate | Combine caller-supplied, precomputed local_result / cisco_result values with required evaluation_id, direction, and mode, plus optional model/scanner/content/timing metadata. It does not scan arbitrary content and returns a GuardrailOutput with action, severity, reason, and scanner_sources. |
GET | /v1/guardrail/config | Return the active guardrail config snapshot. |
PATCH | /v1/guardrail/config | Patch supported guardrail runtime fields into the active DefenseClaw config file, validate the full YAML file, and apply it through the central reloader. Body is JSON, not raw YAML. Supported fields: mode, scanner_mode, block_message, connector, hilt_enabled, hilt_min_severity. Managed-enterprise deployments reject this API mutation. |
Changing connector uses restart semantics so listener and hook state are rebuilt; it is not accepted as an in-place connector swap.
Enforcement logging
These endpoints manage the durable enforcement allow/block lists.
| Method | Path | Purpose |
|---|---|---|
POST, DELETE | /enforce/block | Add a block, or remove it with DELETE. |
POST | /enforce/allow | Add an allow and re-enable a disabled skill/plugin when required. |
GET | /enforce/blocked | List blocked entries. |
GET | /enforce/allowed | List allowed entries. |
Audit
| Method | Path | Purpose |
|---|---|---|
POST | /audit/event | Append one audit-event JSON object to the configured audit logger/store. The production OpenClaw extension client uses this route; managed connector hook routes audit internally. |
GET | /alerts | Return recent alert rows. limit defaults to 50 and is capped at 500. |
POST | /api/v1/alerts/disposition | Preview or apply an audited alert acknowledgement/disposition operation. |
There is no general audit-history or streaming HTTP route. Read/export history through the CLI:
defenseclaw-gateway audit export --output audit.jsonl # JSONL of audit_events
tail -f ~/.defenseclaw/gateway.jsonl | jq # Optional configured v8 JSONL destination
defenseclaw alerts # Recent alerts (paginated)
defenseclaw tui # Live dashboardAudit export includes the legacy details text and, when present, first-class structured JSON from audit_events.structured_json. Connector hook rows use schema: "defenseclaw.hook.v1"; older parsers can still read the mirrored details_json= token inside details.
Config
| Method | Path | Purpose |
|---|---|---|
POST | /config/patch | Bridge {path, value} to the connected upstream agent gateway's WebSocket config.patch RPC. It does not write DefenseClaw's config.yaml; an absent client returns 503, while an RPC/disconnection failure returns 502. |
Runtime control and internal observability bridges
These authenticated routes are narrow process/CLI integration seams rather than general-purpose ingestion APIs.
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/admin/shutdown | Request graceful shutdown. Restricted to loopback and requires the current PID and data directory identity. |
POST | /api/v1/telemetry/canary | Emit a trace canary through the active observability-v8 runtime. |
POST | /api/v1/watchdog/recovery | Record a watchdog recovery metric. Restricted to loopback. |
POST | /api/v1/observability/destination-test/activity | Persist destination-test compliance activity. Restricted to loopback and the exact python-cli client marker. |
POST | /api/v1/observability/cli | Hand validated CLI events to the process-owned observability-v8 runtime. |
AI usage / discovery (AIBOM)
The continuous AI Discovery surface — see AI Discovery for the operator workflow.
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/agents/discovery | Receive an agent-discovery report from the on-host scanner. |
GET | /api/v1/ai-usage | Current continuous-discovery snapshot (summary plus agent, process, endpoint, component, and local-model signals). Local responses retain each model's dedicated model block. |
POST | /api/v1/ai-usage/scan | Trigger an on-demand AI usage scan. |
POST | /api/v1/ai-usage/discovery | Ingest a validated external AI-discovery report. |
GET | /api/v1/ai-usage/components | Aggregated components across the active workspace. |
GET | /api/v1/ai-usage/components/{ecosystem}/{name}/locations | Where the component was detected. |
GET | /api/v1/ai-usage/components/{ecosystem}/{name}/history | Detection history for one component. |
GET | /api/v1/ai-usage/confidence/policy | Show the active confidence-scoring policy. |
POST | /api/v1/ai-usage/confidence/policy/validate | Dry-run validation of a candidate policy file. |
Correlation ledger
Each read route accepts exactly one supported identity anchor (for example
record_id, evaluation_id is not a supported query key here,
semantic_event_id, session_id, trace_id, or tool_invocation_id) and
supports bounded cursor pagination.
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/correlation/graph | Return the evidence-backed identity graph around an anchor. |
GET | /api/v1/correlation/explain | Explain how records are linked to an anchor. |
GET | /api/v1/correlation/timeline | Return the correlated event timeline. |
GET | /api/v1/correlation/conflicts | Return identity conflicts associated with an anchor. |
Codex bridge
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/codex/notify | Codex agent-turn-complete notifier. The Codex notify-bridge.sh shim posts each turn's JSON arg here so the gateway can audit turn counts and completion reasons. |
OTLP receiver
The gateway accepts OTLP-HTTP from configured connectors. Both OTLP JSON and
protobuf content types are accepted; decoding is implemented in
internal/gateway/otel_ingest.go. Request bodies are bounded at 64 MiB; larger
batches receive HTTP 413 and are recorded as content-free body_too_large
rejections.
| Method | Path | Purpose |
|---|---|---|
POST | /v1/logs | Ingest OTLP logs. |
POST | /v1/metrics | Ingest OTLP metrics. |
POST | /v1/traces | Ingest OTLP traces. |
POST | /otlp/{source}/{token}/v1/{signal} | Connector-scoped logs, metrics, or traces for a native exporter that cannot set an auth header. The path token is accepted only over loopback and is removed from route telemetry. |
See internal/gateway/otel_ingest.go for the parsing details and Local observability for the operator setup.
Verdict envelope
All four /api/v1/inspect/* endpoints serialize the same
ToolInspectVerdict:
{
"action": "block | confirm | alert | allow",
"raw_action": "block",
"severity": "CRITICAL | HIGH | MEDIUM | LOW | INFO | NONE",
"confidence": 0.93,
"reason": "matched: CMD-RM-RF:Recursive force delete from critical root path",
"findings": ["CMD-RM-RF:Recursive force delete from critical root path"],
"detailed_findings": [
{
"rule_id": "CMD-RM-RF",
"title": "Recursive force delete from critical root path",
"severity": "CRITICAL",
"confidence": 0.95,
"evidence": "rm -rf /",
"tags": ["destructive", "shell"]
}
],
"mode": "action | observe",
"would_block": true,
"approval_timeout_ms": 45000
}Notable behaviours:
actionis the effective verdict, not the raw policy decision.applyMode()downgradesblock,confirm, andalerttoallowoutside action mode and preserves the original inraw_action. It setswould_block: trueonly for a downgradedblock; downgradedconfirmandalertleave that field false/omitted.confirmis surface-dependent. A native OpenClaw tool-approval caller can receiveconfirmand resolve it in the plugin. A non-native caller cannot safely pause, so the inspect handler fails the confirmation closed toblock. Proxy-lane confirmations may be resolved by the in-processHILTApprovalManager; unsupported proxy surfaces degrade toalert. There is no/v1/hilt/*HTTP API.evaluation_idis the runtime join key in telemetry. Inspect calls stamp it on structured JSONL and audit/scan rows, but the currentToolInspectVerdictHTTP schema does not exposeevaluation_idorrule_ids. Connector-hook responses do expose both fields, as shown below. See Observability §1.4 for the per-surface contract.- Pattern-rule and CodeGuard decisions populate both representations for
backward compatibility. Clean verdicts can omit details, and static, MCP, or
AID merge paths can add string
findingswithout synthesizing matchingdetailed_findings. - Optional fields are omitted when empty. In particular,
approval_timeout_msis absent when its value is zero. A structured finding can additionally includetool_capability_class; it has noremediationfield. - Empty request/response content takes a fast allow path. Those two
handlers return the same verdict type, but before
applyMode()runs; the serialized non-optionalmodeis therefore an empty string andraw_actionis absent.
Other endpoints return their own shapes — /v1/skill/scan returns a scanner-specific envelope, /audit/event returns {"status": "ok"}, and /skill/disable returns {"status": "disabled", "skillKey": "..."}. Always confirm against the handler code before assuming a shape.
Connector hook responses
A connector hook response can carry evaluation_id and the top rule_ids
when the evaluation produced correlation data:
{
"action": "allow | block | deny | …",
"reason": "rule X fired",
"findings": ["rule.id.one:First finding", "rule.id.two:Second finding"],
"evaluation_id": "eval-c1d0…",
"rule_ids": ["rule.id.one", "rule.id.two"]
}Connector-hook responses expose a string findings list, not the inspect
endpoint's detailed_findings objects. Pattern-rule entries normally use
rule_id:title; some scanner-specific paths emit bare finding IDs.
rule_ids is the canonical bare-ID list populated with evaluation_id when
the hook evaluation produced correlation data.
For /api/v1/inspect/*, evidence is redacted by default.
X-DefenseClaw-Reveal-PII: 1 requests raw response evidence. The tool-inspect
handler records an inspect-reveal audit event; the request, response, and
tool-response handlers currently reveal without that extra audit event.
Headers
| Header | Direction | Purpose |
|---|---|---|
X-DefenseClaw-Token, Authorization: Bearer ..., or X-DC-Auth: Bearer ... | request | Master gateway authentication. Every route except GET /health requires either this credential or a route-appropriate scoped token. |
X-DefenseClaw-Client | request | CSRF marker — any non-empty caller identifier (cli, openclaw-plugin, inspect-hook/1.0). Required on non-GET/HEAD requests except the constrained loopback path-token OTLP case described above. |
X-DefenseClaw-Connector | request | On loopback generic inspect routes, selects the registered connector whose scoped hook token is being presented. |
X-DefenseClaw-Source | request | On loopback /v1/{logs,metrics,traces}, selects and must match a header-scoped Codex or Claude Code OTLP token. |
X-DefenseClaw-Request-Id | request (optional), response | Caller-supplied correlation id. The gateway also accepts X-Request-Id and X-Correlation-Id; if none is supplied, it mints one. The chosen ID is always returned as X-DefenseClaw-Request-Id. See requestctx.go. |
CLI commands
Every defenseclaw verb, grouped by what you are trying to do — first run, setup, audit, scanning, gateway control, status, uninstall.
Configuration
~/.defenseclaw/config.yaml schema, environment variables, on-disk layout, and per-connector source-of-truth files. The single source of truth for "where does this setting live?"