Zum Inhalt springen

WebSocket-Ereignisse

Connection

Human WebSocket

GET wss://api.hashee.ai/ws/human

After upgrade, send auth within 5 seconds:

{ "type": "auth", "token": "<access_token>" }

Agent WebSocket

GET wss://api.hashee.ai/ws/agent?agent_id={agentId}

After upgrade, send auth within 5 seconds:

{ "type": "auth", "token": "hsk_...", "agent_id": "{agentId}" }

Auth Response

Success:

{ "type": "auth.ok" }

Failure:

{
"type": "auth.error",
"reason": "invalid_token",
"message": "Token expired",
"i18n_key": "error.auth.expired"
}

Client-to-Server Frames

auth.renew

Renew the access token on an existing connection. Send after refreshing the JWT via REST:

{ "type": "auth.renew", "access_token": "new_jwt..." }

Server-to-Client Events

Message Events

message.new

A new message in a conversation:

{
"type": "message.new",
"conversation_id": "uuid",
"message_id": "uuid",
"sender_id": "uuid",
"sender_type": "human",
"content_type": "text",
"encrypted_payload": "base64...",
"conversation_seq": 42,
"created_at": "2026-01-01T00:00:00Z"
}

message.ack

Acknowledgment that a sent message was received by the server.

message.read

A participant read messages up to a certain sequence number.

message.recalled

A message was recalled by the sender:

{
"type": "message.recalled",
"message_id": "uuid",
"conversation_id": "uuid",
"recalled_by": "uuid"
}

message.status_updated

Message delivery status changed.

message.pinned

A message was pinned in a group.

Stream Events

stream.start

An agent began streaming a response.

stream.delta

A chunk of streamed content:

{
"type": "stream.delta",
"conversation_id": "uuid",
"encrypted_payload": "base64..."
}

stream.done

Stream completed with the full encrypted payload for persistence.

stream.abort

Stream was cancelled by the agent.

stream.error

Stream timed out or hit a limit.

Relationship Events

relation.established

A new user started using the agent:

{
"type": "relation.established",
"payload": {
"user_id": "uuid",
"display_name": "Alice",
"avatar_url": "https://...",
"language": "en",
"referral_source": "invite_link",
"public_key": "base64..."
}
}

The SDK automatically caches the public_key from this event.

relation.terminated

User disconnected from the agent:

{ "type": "relation.terminated", "payload": { "user_id": "uuid" } }

relation.suspended

User was suspended by the creator:

{ "type": "relation.suspended", "payload": { "user_id": "uuid" } }

relation.restored

User was restored by the creator:

{ "type": "relation.restored", "payload": { "user_id": "uuid" } }

Artifact Events

artifact_response

User responded to an artifact (form submission, button click):

{
"type": "artifact_response",
"payload": {
"conversation_id": "uuid",
"message_id": "uuid",
"ref_artifact": "artifact_id",
"ref_action": "submit",
"based_on_revision": 1,
"values": { "name": "My Project" }
}
}

artifact_update

An agent updated an artifact (WebSocket delivery to human clients).

artifact.expired

An artifact’s TTL expired:

{
"type": "artifact.expired",
"payload": {
"conversation_id": "uuid",
"message_id": "uuid",
"artifact_id": "uuid"
}
}

Agent Events

agent.governance

Agent governance status changed (WebSocket only, not delivered via webhook):

{
"type": "agent.governance",
"payload": {
"agent_template_id": "uuid",
"governance_status": "suspended",
"reason": "Policy violation"
}
}

If status is suspended or banned, the WebSocket connection is terminated.

agent.status

Agent online/offline status changed.

agent.typing

Agent is typing.

Reaction Events

reaction.update

Reactions on a message changed (aggregate state):

{
"type": "reaction.update",
"payload": {
"message_id": "uuid",
"reactions": [
{ "emoji": "thumbsup", "count": 3, "user_ids": ["uuid1", "uuid2", "uuid3"] }
]
}
}

Group Events

group.updated

Group info changed (name, avatar, settings):

{
"type": "group.updated",
"payload": {
"conversation_id": "uuid",
"changes": { "name": "New Group Name" }
}
}

Session Events

auth.expiring

Advisory: access token is about to expire. Client should refresh via REST and send auth.renew:

{ "type": "auth.expiring", "expires_in_seconds": 60 }

session.invalidated

Server terminated the session (device kicked, password changed, etc.):

{
"type": "session.invalidated",
"payload": {
"reason": "device_removed",
"message": "Session terminated",
"i18n_key": "error.session.invalidated"
}
}

error

Generic WebSocket error:

{
"type": "error",
"payload": {
"code": "RATE_LIMITED",
"message": "Too many requests",
"i18n_key": "error.rate_limited"
}
}

Event Delivery by Transport

EventWebSocketWebhook
message.newYesYes
relation.establishedYesYes
relation.terminatedYesYes
relation.suspendedYesYes
relation.restoredYesYes
artifact_responseYesYes
agent.governanceYesNo
reaction.updateYesNo
group.updatedYesNo
artifact.expiredYesNo
session.invalidatedYesNo
auth.expiringYesNo

Long Polling delivers the same event set as Webhook.

Next Steps