Skip to documentation
Documentation navigation

Documentation navigation

Documentation / guides

Gate responses

Deliver approval, denial, and form responses.

developer

Answer a live gate with POST /v1/sessions/{sid}/gates/{gid}. The HTTP layer validates UUIDs and JSON shape, stamps the response as user supplied, and delegates gate semantics and durable acceptance to the live session.

Request shape

The route accepts the public gate.ResponseRequest value. sid and gid are UUID path values; a malformed value returns the normal invalid_parameter error envelope with status 400. A valid session must also be present in the process-local live registry.

// gate.ResponseRequest is the complete HTTP request payload.
type ResponseRequest struct {
	Action string                      `json:"action,omitempty"`
	Values map[string]json.RawMessage  `json:"values,omitempty"`
}

The values map keeps each form answer as raw JSON until the gate’s own validator interprets it. The route does not accept a source field. The server constructs this envelope before calling RespondGate:

resp := gate.GateResponse{
	GateID: gid,
	Action: req.Action,
	Values: req.Values,
	Source: gate.ResponseSource{Kind: gate.ResponseFromUser},
}
err := live.RespondGate(ctx, resp)

For approval gates, the domain parser recognizes these exact action strings:

ActionMeaning
ApproveApprove this request.
Approve always for this workspacePersist the workspace-scoped approval when the gate supports it.
DenyRefuse this request.

Those values are checked by gate.ParseApprovalAction or the gate kind’s validator. An empty body decodes as an empty request and is left for the live session to reject as action_invalid; malformed JSON is rejected by the HTTP boundary as invalid_body.

Durable acceptance

On success the server returns 202 Accepted with the JSON body {}. This is an acceptance boundary, not a claim that the blocked loop has already consumed the answer. RespondGate may append the resolution and route an in-memory command; the caller should observe the resulting enduring event or status transition through the session event stream.

The gate ID in the path is authoritative. The body carries action and values, not another gate identifier. A response is only routed to a session found in the live registry, so this endpoint cannot answer a session that exists solely in durable storage and has not been restored into this process.

%%{init: {"theme":"dark"}}%%
sequenceDiagram
    participant C as Client
    participant H as HTTP handler
    participant R as Live registry
    participant S as LiveSession
    participant J as Session journal
    C->>H: POST /v1/sessions/{sid}/gates/{gid}
    H->>H: Parse UUIDs and decode ResponseRequest
    H->>R: Look up sid
    R-->>H: LiveSession or miss
    H->>S: RespondGate(user-stamped response)
    S->>J: Append gate resolution when accepted
    J-->>S: Durable acceptance
    H-->>C: 202 {}

The HTTP handler never reports consumption as part of the 202 response. Use GET /v1/sessions/{sid}/events to follow the public event stream.

Status mapping

The handler inspects the stable GateErrorKind() value exposed by the session error chain. It does not expose the wrapped cause in the response body.

Gate kindHTTP statusError codeRetryable
not_found404gate_not_foundfalse
action_invalid400gate_action_invalidfalse
kind_mismatch400gate_kind_mismatchfalse
not_ready409gate_not_readyfalse
capacity503gate_capacitytrue
append_failed500internalfalse
unknown kind or non-gate error500internalfalse

All failures use the nested JSON envelope described in errors-and-status. A capacity response is the only gate-specific retryable response because the gate directory may become able to accept work after it drains.

Source and runnable proof

The route, payload decode, provenance stamp, and status table are implemented in handlers_gate.go. The request and mapping cases are exercised in handlers_gate_test.go, and the domain response envelope is defined in response.go. Run the focused package tests from the harness repository:

go test ./pkg/serve

← back to documentation