website/src/content/docs/actors/debugging.mdx
All debugging endpoints in this guide are available both locally and in production. In local development, the base URL is http://localhost:6420 with no authentication. In production (Rivet Cloud or self-hosted), you connect to your Rivet Engine endpoint with a token.
All examples in this guide use these shell variables. Extract them from your RIVET_ENDPOINT (https://<namespace>:<token>@<host>):
# From RIVET_ENDPOINT=https://my-namespace:[email protected]
export RIVET_API="https://api.rivet.dev"
export RIVET_NAMESPACE="my-namespace"
export RIVET_TOKEN="sk_abc123"
# For local development:
# export RIVET_API="http://localhost:6420"
Rivet Cloud issues two token types: sk_ (secret key, server-side only) and pk_ (public key, client-safe). For debugging, always use sk_. See Endpoints for more details.
The management API runs on the manager base path (default root path) and is used to list, create, and look up actors.
| Environment | Authentication |
|---|---|
| Local development | No authentication required. All endpoints are accessible without tokens. |
| Self-hosted engine | Set RIVET_TOKEN to enable authenticated access to restricted endpoints like KV. |
| Rivet Cloud | Authentication is enforced by your deployment entrypoint. For manager KV access, use the manager token header below when enabled. |
Restricted endpoints (like KV reads) require the x-rivet-token header when RIVET_TOKEN is configured:
curl "$RIVET_API/actors/{actor_id}/kv/keys/{base64_key}" \
-H "x-rivet-token: $RIVET_TOKEN"
# List all actors with a given name
curl "$RIVET_API/actors?name=my-actor&namespace=$RIVET_NAMESPACE" \
-H "Authorization: Bearer $RIVET_TOKEN"
# Look up one actor by key (name is required when key is provided)
curl "$RIVET_API/actors?name=my-actor&key=%5B%22my-key%22%5D&namespace=$RIVET_NAMESPACE" \
-H "Authorization: Bearer $RIVET_TOKEN"
# List actors by IDs (comma-separated)
curl "$RIVET_API/actors?actor_ids=id1,id2&namespace=$RIVET_NAMESPACE" \
-H "Authorization: Bearer $RIVET_TOKEN"
Rules:
key requires name.actor_ids cannot be combined with name or key.Returns:
{
"actors": [
{
"actor_id": "abc123",
"name": "my-actor",
"key": "[\"default\"]",
"namespace_id": "default",
"create_ts": 1706000000000
}
]
}
POST /actors creates a new actor.
curl -X POST "$RIVET_API/actors?namespace=$RIVET_NAMESPACE" \
-H "Authorization: Bearer $RIVET_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name": "my-actor",
"runner_name_selector": "default",
"crash_policy": "restart"
}'
PUT /actors creates an actor if it does not exist, otherwise returns the existing one.
curl -X PUT "$RIVET_API/actors?namespace=$RIVET_NAMESPACE" \
-H "Authorization: Bearer $RIVET_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name": "my-actor",
"key": "[\"default\"]",
"runner_name_selector": "default",
"crash_policy": "restart"
}'
Returns the actor object with its actor_id.
curl "$RIVET_API/actors/names?namespace=$RIVET_NAMESPACE" \
-H "Authorization: Bearer $RIVET_TOKEN"
Returns all registered actor names and their metadata.
Requires authentication (see above).
curl "$RIVET_API/actors/{actor_id}/kv/keys/{base64_key}" \
-H "x-rivet-token: $RIVET_TOKEN"
Returns the value stored at the given key.
See the OpenAPI spec for the full schema of all management endpoints.
Use the runner endpoints to debug scheduler capacity and provider configuration (for example serverless URL, headers, and limits) through the Rivet API.
curl "$RIVET_API/runners/names?namespace=$RIVET_NAMESPACE" \
-H "Authorization: Bearer $RIVET_TOKEN"
Returns the runner pools available in the namespace:
{
"names": ["default", "gpu-workers"],
"pagination": { "cursor": null }
}
curl "$RIVET_API/runners?namespace=$RIVET_NAMESPACE&name=default&include_stopped=true&limit=100" \
-H "Authorization: Bearer $RIVET_TOKEN"
Useful fields when debugging:
remaining_slots / total_slots for capacity.drain_ts and stop_ts for shutdown behavior.last_ping_ts and last_connected_ts for connectivity.curl "$RIVET_API/runner-configs?namespace=$RIVET_NAMESPACE&runner_name=default" \
-H "Authorization: Bearer $RIVET_TOKEN"
Returns the configured provider settings per datacenter and the latest pool error (if any):
{
"runner_configs": {
"default": {
"datacenters": {
"dc-1": {
"serverless": {
"url": "https://your-deployment.example.com/rivet",
"headers": { "Authorization": "Bearer token" },
"request_lifespan": 55,
"slots_per_runner": 1,
"max_runners": 10
},
"runner_pool_error": null
}
}
}
},
"pagination": { "cursor": null }
}
runner_pool_error mirrors actor scheduling errors such as serverless_http_error, serverless_connection_error, and serverless_stream_ended_early.
Use this to test whether Rivet can reach your serverless provider URL and read runner metadata:
curl -X POST "$RIVET_API/runner-configs/serverless-health-check?namespace=$RIVET_NAMESPACE" \
-H "Authorization: Bearer $RIVET_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-deployment.example.com/rivet",
"headers": {
"Authorization": "Bearer token"
}
}'
Possible responses:
{ "success": { "version": "1.2.3" } }
{
"failure": {
"error": {
"message": "non-success status from metadata endpoint",
"details": "received status 503"
}
}
}
If you deploy new actor code or routes and metadata has not updated yet, force a refresh:
curl -X POST "$RIVET_API/runner-configs/default/refresh-metadata?namespace=$RIVET_NAMESPACE" \
-H "Authorization: Bearer $RIVET_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'
All actor-level endpoints are accessed through the gateway. The gateway routes requests to the correct actor instance using the actor ID in the URL path:
{RIVET_API}/gateway/{actor_id}/{path}
The gateway only accepts actor IDs, not names. Use GET /actors?name=... from the management API to look up actor IDs first.
Standard actor endpoints (health, actions, requests) and inspector endpoints have separate authentication requirements.
| Environment | Authentication |
|---|---|
| Local development | No authentication required. |
| Self-hosted engine | The Rivet Engine handles authentication at the gateway level. |
| Rivet Cloud | Authentication is handled by the Rivet Cloud platform at the gateway level. |
| Environment | Authentication |
|---|---|
| Local development | No authentication required if RIVET_INSPECTOR_TOKEN is not set. A warning is logged. |
| Self-hosted engine | Set the RIVET_INSPECTOR_TOKEN environment variable. Pass it as a bearer token in the Authorization header. The actor-specific inspector token used by the standalone Inspector UI is also accepted. |
| Rivet Cloud | Token is required. Pass it as a bearer token in the Authorization header. The actor-specific inspector token used by the standalone Inspector UI is also accepted. |
curl "$RIVET_API/gateway/{actor_id}/inspector/summary" \
-H 'Authorization: Bearer YOUR_INSPECTOR_TOKEN'
In Rivet Cloud, each actor generates a unique inspector token on first start and persists it in its internal KV store. The Rivet dashboard retrieves this token automatically, but if you need it for direct API access, fetch it from the management KV endpoint.
The inspector token is stored at internal KV key 0x03 (base64: Aw==). The response value is also base64-encoded.
# Fetch the inspector token for a specific actor
ACTOR_ID="your-actor-id"
RESPONSE=$(curl -s "$RIVET_API/actors/$ACTOR_ID/kv/keys/Aw==" \
-H "x-rivet-token: $RIVET_TOKEN")
# Extract and decode the base64 value
INSPECTOR_TOKEN=$(echo "$RESPONSE" | jq -r '.value' | base64 -d)
# Use it to call inspector endpoints
curl "$RIVET_API/gateway/$ACTOR_ID/inspector/summary" \
-H "Authorization: Bearer $INSPECTOR_TOKEN"
These are the built-in actor endpoints available through the gateway:
# Health check
curl $RIVET_API/gateway/{actor_id}/health
# Metadata
curl $RIVET_API/gateway/{actor_id}/metadata
# Call an action
curl -X POST $RIVET_API/gateway/{actor_id}/action/myAction \
-H 'Content-Type: application/json' \
-d '{"args": [1, 2, 3]}'
# Send queue message (body includes queue name)
curl -X POST $RIVET_API/gateway/{actor_id}/queue \
-H 'Content-Type: application/json' \
-d '{"name":"jobs","body":{"id":"job-1"}}'
# Send queue message (queue name in path)
curl -X POST $RIVET_API/gateway/{actor_id}/queue/jobs \
-H 'Content-Type: application/json' \
-d '{"body":{"id":"job-1"}}'
# Send queue message and wait for completion (optional timeout in ms)
curl -X POST $RIVET_API/gateway/{actor_id}/queue/jobs \
-H 'Content-Type: application/json' \
-d '{"body":{"id":"job-1"},"wait":true,"timeout":5000}'
# Forward an HTTP request to the actor's onRequest handler
curl $RIVET_API/gateway/{actor_id}/request/my/custom/path
Queue send responses include:
{ "status": "completed", "response": null }
If wait: true and the timeout is reached, status is "timedOut".
The inspector HTTP API exposes JSON endpoints for querying and modifying actor internals at runtime. These are designed for agent-based debugging and tooling.
curl $RIVET_API/gateway/{actor_id}/inspector/state
Returns the actor's current persisted state:
{
"state": { "count": 42, "users": [] },
"isStateEnabled": true
}
curl -X PATCH $RIVET_API/gateway/{actor_id}/inspector/state \
-H 'Content-Type: application/json' \
-d '{"state": {"count": 0, "users": []}}'
Returns:
{ "ok": true }
curl $RIVET_API/gateway/{actor_id}/inspector/connections
Returns all active connections with their params, state, and metadata:
{
"connections": [
{
"type": "websocket",
"id": "conn-id",
"details": {
"type": "websocket",
"params": {},
"stateEnabled": true,
"state": {},
"subscriptions": 2,
"isHibernatable": true
}
}
]
}
curl $RIVET_API/gateway/{actor_id}/inspector/rpcs
Returns a list of available actions:
{ "rpcs": ["increment", "getCount"] }
curl -X POST $RIVET_API/gateway/{actor_id}/inspector/action/increment \
-H 'Content-Type: application/json' \
-d '{"args": [5]}'
Returns:
{ "output": 47 }
curl $RIVET_API/gateway/{actor_id}/inspector/queue?limit=10
Returns queue status with messages:
{
"size": 3,
"maxSize": 1000,
"truncated": false,
"messages": [
{ "id": 1, "name": "process", "createdAtMs": 1706000000000 }
]
}
Query trace spans in OTLP JSON format:
curl "$RIVET_API/gateway/{actor_id}/inspector/traces?startMs=0&endMs=9999999999999&limit=100"
Returns:
{
"otlp": {
"resourceSpans": [
{
"scopeSpans": [
{
"spans": [
{
"traceId": "abc123",
"spanId": "def456",
"name": "increment",
"startTimeUnixNano": "1706000000000000000"
}
]
}
]
}
]
},
"clamped": false
}
curl $RIVET_API/gateway/{actor_id}/inspector/workflow-history
Returns:
{
"history": null,
"isWorkflowEnabled": false
}
curl $RIVET_API/gateway/{actor_id}/inspector/database/schema
Returns discovered SQLite tables and views when the actor has c.db enabled:
{
"schema": {
"tables": [
{
"table": { "schema": "main", "name": "test_data", "type": "table" },
"columns": [
{ "cid": 0, "name": "id", "type": "", "notnull": 0, "dflt_value": null, "pk": 0 }
],
"foreignKeys": [],
"records": 2
}
]
}
}
curl "$RIVET_API/gateway/{actor_id}/inspector/database/rows?table=test_data&limit=100&offset=0"
Returns paged rows for a specific SQLite table or view:
{
"rows": [
{
"id": 1,
"value": "Alice",
"payload": "",
"created_at": 1706000000000
}
]
}
Run manual SQL against an actor's SQLite database. This supports both read-only queries and mutations.
curl -X POST http://localhost:6420/gateway/{actor_id}/inspector/database/execute \
-H 'Content-Type: application/json' \
-d '{
"sql": "SELECT id, value FROM test_data WHERE value = ? ORDER BY id DESC",
"args": ["alpha"]
}'
Returns:
{
"rows": [
{ "id": 2, "value": "alpha" }
]
}
You can also use named SQLite bindings through a properties object:
curl -X POST http://localhost:6420/gateway/{actor_id}/inspector/database/execute \
-H 'Content-Type: application/json' \
-d '{
"sql": "SELECT id, value FROM test_data WHERE value = :value ORDER BY id DESC",
"properties": {
"value": "alpha"
}
}'
For mutations, use RETURNING if you want rows back. Otherwise the statement still runs and rows is empty:
curl -X POST http://localhost:6420/gateway/{actor_id}/inspector/database/execute \
-H 'Content-Type: application/json' \
-d '{
"sql": "INSERT INTO test_data (value, created_at) VALUES (?, ?) RETURNING id, value",
"args": ["beta", 1706000000000]
}'
For workflow-enabled actors, history is a JSON object with nameRegistry, entries, and entryMetadata. Step outputs, loop state, and message payloads are decoded from CBOR into normal JSON values.
Reset a workflow to a specific step and restart execution immediately. Omitting entryId replays the workflow from the beginning.
curl -X POST http://localhost:6420/gateway/{actor_id}/inspector/workflow/replay \
-H 'Content-Type: application/json' \
-d '{"entryId":"workflow-step-id"}'
Returns the same JSON shape as /inspector/workflow-history:
{
"history": {
"nameRegistry": ["step-one", "step-two"],
"entries": [],
"entryMetadata": {}
},
"isWorkflowEnabled": true
}
Get a full snapshot of the actor in a single request:
curl $RIVET_API/gateway/{actor_id}/inspector/summary
Returns:
{
"state": { "count": 42 },
"connections": [],
"rpcs": ["increment", "getCount"],
"queueSize": 0,
"isStateEnabled": true,
"isDatabaseEnabled": false,
"isWorkflowEnabled": false,
"workflowHistory": null
}
When workflow history is present in /inspector/summary, workflowHistory is returned as the same encoded byte array used by /inspector/workflow-history.
curl $RIVET_API/gateway/{actor_id}/inspector/metrics
Returns in-memory metrics for the current actor wake cycle. Metrics are not persisted and reset when the actor sleeps and wakes again.
Includes counters for action_calls, action_errors, action_duration_ms, connections_opened, connections_closed, sql_statements, sql_duration_ms, and kv_operations.
Inspector endpoints are safe to poll. For live monitoring, poll at 1-5 second intervals. The /inspector/summary endpoint is useful for periodic snapshots since it returns all data in a single request.
The full OpenAPI specification including all management and actor endpoints is available:
rivetkit-openapi/openapi.json/doc on the manager when running locally