Skip to main content
GET
/
api
/
v1
/
agents
/
{agentId}
/
conversations
/
{convId}
/
events
SSE stream of new messages on the conversation.
curl --request GET \
  --url https://openapi.beeos.ai/api/v1/agents/{agentId}/conversations/{convId}/events \
  --header 'Authorization: Bearer <token>'
"<string>"

Authorizations

Authorization
string
header
required

Pass a user JWT or a oag_ User API Key on the Authorization: Bearer <token> header. Both are validated by openapi-gateway against the Auth service.

Both credential types are user-scoped: every key (and every JWT) is bound to exactly one owner, and every route grants the caller full access to that owner's own resources. Cross-tenant access is denied by owner-ACL inside the handlers — there is no per-route scope vocabulary on this API.

Removed in v1.1.0: the legacy agents:* / tasks:* / files:* / instances:* scope set has been dropped together with the 403 insufficient_scope error. Existing oag_ keys automatically gain full owner-level access and do not need to be re-issued. SDK calls that previously passed scopes to createAPIKey should drop the argument. See the changelog at the bottom of this spec for the full migration note.

Path Parameters

agentId
string
required
Maximum string length: 128
convId
string
required
Maximum string length: 128

Query Parameters

since
integer<int64>

Replay cursor. Matches the offset field on the last received event — clients persist this value and pass it back on reconnect to resume without gaps or duplicates (Last-Event-ID semantics; the wire spelling stays since for backward compatibility with the pre-v2 SSE clients).

Special values:

  • omitted / 0 — full history replay.
  • <offset> — resume strictly AFTER the given offset.

Unlike the task variant, this stream never auto-closes on a terminal envelope — conversations stay open across many turns and emit further agent_reply events. Persist since across reconnect ranges to avoid dropping turns during network blips.

Required range: x >= 0

Response

SSE stream of channel-message envelopes.

Server-Sent Events stream.

Per-event JSON payload format (v3 envelope fields body, state, stop_reason, updated_at are populated whenever the underlying row was written via the v3 path; legacy v1 / v2 rows leave them empty — consumers should fall back to payload.text

  • type to detect terminality):
event: message
data: {
"type": "agent_message_chunk", // see below
"message_id": "msg-uuid",
"offset": 5, // monotonic per-channel offset
"in_reply_to": "msg-source-uuid",
"publisher_id": "agent-identity",
"payload": { ... }, // opaque, per-type
"body": "Hello, world", // v3 cumulative text (optional)
"state": "streaming", // v3 lifecycle (optional)
"stop_reason": "", // v3 terminal reason (only set when state != streaming)
"created_at": "2026-05-14T18:00:00.000Z",
"updated_at": "2026-05-14T18:00:00.123Z"
}

Backfill truncation frame — emitted ONCE when the server caps the historical replay window (see since=<offset> semantics above). Field shape matches TaskSSEBackfillTruncated. Clients should resume from oldest_redis_offset after seeing this frame:

event: backfill_truncated
data: {
"since": 100,
"oldest_redis_offset": 1500,
"hint": "stream evicted entries older than oldest_redis_offset"
}

Terminal events:

event: end
data: { "reason": "task_terminal" } # task only: auto-close after agent_reply / agent_reply_error / agent.refuse / agent_busy
event: end
data: { "reason": "stream_closed" } # MS closed the upstream stream
event: end
data: { "reason": "channel_closed" } # conversation only: caller (or peer) deleted the conversation

end.reason enum:

reasonsurfacewhen
task_terminaltaskterminal reply auto-closed the SSE
stream_closedtask + conversationMS closed the upstream stream
channel_closedconversationthe underlying channel was deleted

Well-known message type values:

typemeaning
chat_messagecaller's prompt
agent_thought_chunkagent reasoning (incremental)
agent_message_chunkagent reply delta (incremental)
agent_reply_deltaterminal-bound streaming delta
agent_replyterminal success reply
agent_reply_errorterminal failure reply
agent.input_requiredpause awaiting user.continue
agent.auth_requiredpause awaiting user.auth_grant
user.continuecaller resume of input_required
user.auth_grantcaller resume of auth_required
chat_cancelcaller-initiated cancel