Poll & Heartbeat
poll/heartbeat, batchWork, gitCredentials.
Once registered, a worker runs a continuous loop: it sends a heartbeat to report its health and polls for new work. This page describes both endpoints and the full structure of the poll response, including batch work items and git credentials.
Heartbeat
Send a heartbeat on the interval provided by the registration response (heartbeatIntervalSeconds). A missed heartbeat causes the platform to mark the worker as unhealthy and eventually stop dispatching new sessions to it.
Daemon-native heartbeat
POST /v1/daemon/heartbeat
Authorization: Bearer <runtimeJwt>
Content-Type: application/jsonRequest body
{
"workerId": "wkr_01abc...",
"hostname": "build-host-01",
"status": "idle",
"activeSessions": 0,
"maxSessions": 4,
"region": "us-east-1",
"capabilities": ["code-execution"],
"version": "0.11.0"
}| Field | Type | Required | Description |
|---|---|---|---|
workerId | string | Yes | Worker ID from registration |
hostname | string | Yes | Human-readable host identifier |
status | string | Yes | One of: idle, busy, draining |
activeSessions | number | Yes | Current number of active sessions |
maxSessions | number | Yes | Maximum concurrent session capacity |
region | string | No | Geographic region |
capabilities | string[] | No | Declared capability tokens |
version | string | No | Daemon version |
Success response (200)
{
"ok": true,
"serverTimeMs": 1748880000000
}AF-compatible heartbeat
POST /api/workers/{workerId}/heartbeat
Authorization: Bearer <runtimeJwt>
Content-Type: application/jsonRequest body
{
"status": "idle",
"activeSessions": 0,
"maxSessions": 4
}Poll for work
Poll returns any sessions queued for this worker, plus inbox messages and optional batch work items.
GET /api/workers/{workerId}/poll
Authorization: Bearer <runtimeJwt>The platform enforces that the JWT sub claim matches the {workerId} URL parameter. A mismatched token returns 403 Forbidden.
Poll response
{
"work": [
{
"sessionId": "sess_01abc...",
"issueId": "linear:abc123",
"projectId": "proj_01abc...",
"workType": "feature",
"agentCard": { "... agent card object ..." },
"systemPromptOverride": null,
"gitCredentials": {
"token": "ghp_...",
"host": "github.com",
"expiresAt": "2026-06-02T13:00:00Z"
}
}
],
"inboxMessages": [],
"hasInboxMessages": false,
"preClaimed": true,
"claimedSessionIds": ["sess_01abc..."],
"batchWork": []
}Work item fields
| Field | Type | Description |
|---|---|---|
sessionId | string | Unique session ID. Use in all session lifecycle calls. |
issueId | string | Provider-namespaced issue identifier (e.g. linear:ABC-123) |
projectId | string | Platform project ID |
workType | string | SDLC work type: feature, bug_fix, refactor, research, etc. |
agentCard | object | Resolved agent card for this session (includes system prompt, capabilities, tool config) |
systemPromptOverride | string | null | Override system prompt, if set on the session (takes precedence over agent card) |
gitCredentials | object | null | Short-lived git credentials for repo access |
authMode | string | Auth mode for this session: byok, metered, shared, host-session, local |
gitCredentials
When the session requires repository access, gitCredentials provides a short-lived token:
{
"token": "ghs_...",
"host": "github.com",
"username": "x-access-token",
"expiresAt": "2026-06-02T13:00:00Z"
}Configure git to use it:
git config --global credential.helper store
echo "https://x-access-token:${GIT_TOKEN}@github.com" > ~/.git-credentialsBatch work items
Workers that advertise the code-survival-scan capability receive batchWork[] items in addition to session-based work. These are code survival analysis tasks dispatched in bulk.
{
"batchWork": [
{
"batchItemId": "batch_01abc...",
"type": "code-survival-scan",
"payload": {
"repository": "github.com/my-org/my-repo",
"pool": "RW3",
"commitRange": "abc123..def456"
}
}
]
}Declare the capability at registration to receive these items:
{
"registrationToken": "rsk_live_...",
"capabilities": ["code-execution", "code-survival-scan"]
}Inbox messages
The inboxMessages array carries out-of-band signals for the worker - for example, a user's nudge prompt sent via the Public Sessions API or a stop signal.
{
"inboxMessages": [
{
"messageId": "msg_01abc...",
"type": "prompt",
"payload": { "text": "Focus on the error handling in the login flow." }
}
],
"hasInboxMessages": true
}ACK inbox messages after processing them:
curl -X POST "https://app.rensei.ai/api/sessions/sess_01abc.../inbox/ack" \
-H "Authorization: Bearer <runtimeJwt>" \
-H "Content-Type: application/json" \
-d '{"messageId": "msg_01abc..."}'Pre-claim semantics
When preClaimed is true, the platform has atomically reserved the returned sessions for this worker. The worker must either begin execution or explicitly return the session. There is no separate "claim" step - sessions returned in a poll response are already owned by the calling worker.
Worker loop example (TypeScript)
async function workerLoop(workerId: string, jwt: string) {
while (true) {
// Heartbeat
await fetch(`https://app.rensei.ai/v1/daemon/heartbeat`, {
method: 'POST',
headers: {
Authorization: `Bearer ${jwt}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ workerId, status: 'idle', activeSessions: 0, maxSessions: 4 }),
});
// Poll
const pollRes = await fetch(
`https://app.rensei.ai/api/workers/${workerId}/poll`,
{ headers: { Authorization: `Bearer ${jwt}` } }
);
const { work, inboxMessages } = await pollRes.json();
for (const session of work) {
// dispatch session to agent subprocess
}
await sleep(5000); // use pollIntervalSeconds from registration
}
}Related pages
- Worker Registration - obtain a
workerIdandruntimeJwt - Session Lifecycle - status transitions after picking up work
- Worker Credentials - credential snapshot and rotate-stream SSE