openvibers/openvibe.contracts Commits
chat.vibe.deliver: Actor posts each finished run of a person's OpenVibe Agent into their own Vibe chat named after it (each run is a chat they can open); chat.vibe-deliver-request/result@1; agents gain send_to_vibe (0.214.0) (#218)
Changes
@@@ -6,6 +6,13 @@ the notes were in the tag and commit messages (`git tag -n1`).## 0.214.0 — 2026-10-26++- **`chat.vibe.deliver`** (first-party, sensitive, owned by `chat`; consumer plan §4: "each run is a chat you can++ open"): a first-party service puts a result of the person's own work into their Vibe chats (`POST++ /internal/chat/vibe/deliver`). OpenVibe.Actor posts each finished run of one of their OpenVibe Agents into one chat per++ agent, named after it, as Vibe's message. No AI answer is made and nothing counts against the allowance. Schemas++ `chat.vibe-deliver-request@1` (subject, source { kind agent, id, name }, text in Markdown, url, idempotency_key) and++ `chat.vibe-deliver-result@1` (chat, url, repeated), with fixtures. `actor.agent-manage-request@1` and `-result@1`++ gain `send_to_vibe` (boolean, default true), the agent's switch for it.- **`actor.agent.manage`** lists the suggestions routes (`GET /api/v1/me/agents/:id/suggestions`, `POST…/suggestions/:pid/:action` with apply | dismiss | undo): a personal agent may suggest a line for its instructions after arun that passed its check, which waits for the person (OpenVibe.Actor#115).@@@ -2,7 +2,7 @@"$schema": "https://json-schema.org/draft/2020-12/schema","$id": "https://openvibe.network/contracts/actor/agent-manage-request.v1.json","title": "ActorAgentManageRequest",-- "description": "actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.",++ "description": "actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, send_to_vibe?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.","anyOf": [{"type": "object",@@@ -78,6 +78,10 @@"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$","description": "HH:MM UTC: quiet hours end."},++ "send_to_vibe": {++ "type": "boolean",++ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."++ },"status": {"enum": ["active",@@@ -100,6 +100,10 @@"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$","description": "HH:MM UTC: quiet hours end."},++ "send_to_vibe": {++ "type": "boolean",++ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."++ },"status": {"enum": ["active",@@@ -267,6 +271,10 @@"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$","description": "HH:MM UTC: quiet hours end."},++ "send_to_vibe": {++ "type": "boolean",++ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."++ },"status": {"enum": ["active",@@@ -5096,6 +5096,24 @@"compatibility": "backward","status": "active"},++ {++ "id": "chat.vibe-deliver-request",++ "version": "1.0.0",++ "owner": "chat",++ "schema": "chat/vibe-deliver-request.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active"++ },++ {++ "id": "chat.vibe-deliver-result",++ "version": "1.0.0",++ "owner": "chat",++ "schema": "chat/vibe-deliver-result.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active"++ },{"id": "live.moderation.action","version": "1.0.0",nnew file mode 100644@@@ -0,0 +1,63 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/chat/vibe-deliver-request.v1.json",++ "title": "ChatVibeDeliverRequest",++ "description": "chat.vibe-deliver-request@1: a first-party service puts a result of the person's own work into their Vibe chats (OpenVibe.Actor: each finished run of one of their OpenVibe Agents, when the agent sends its results to Vibe). Chat keeps one chat per source, named after it, and posts the text there as Vibe's message, so each run is a chat they can open and continue. No AI answer is made and nothing counts against their allowance. POST /internal/chat/vibe/deliver, capability chat.vibe.deliver, loopback only.",++ "type": "object",++ "required": [++ "subject",++ "source",++ "text",++ "idempotency_key"++ ],++ "additionalProperties": false,++ "properties": {++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "The person whose work it is, as the calling service vouches (Actor: the agent's owner)."++ },++ "source": {++ "type": "object",++ "required": [++ "kind",++ "id"++ ],++ "additionalProperties": false,++ "properties": {++ "kind": {++ "enum": [++ "agent"++ ]++ },++ "id": {++ "type": "string",++ "pattern": "^[A-Za-z0-9_.:-]{1,64}$",++ "description": "The source's stable id (the agent's agt_ id): one chat per source."++ },++ "name": {++ "type": "string",++ "maxLength": 80,++ "description": "What to call it in the chat's name (the agent's name)."++ }++ }++ },++ "text": {++ "type": "string",++ "minLength": 1,++ "maxLength": 8000,++ "description": "The result, in Markdown (as Vibe's answers are shown)."++ },++ "url": {++ "type": "string",++ "format": "uri",++ "pattern": "^https://",++ "description": "Where the whole run is (its steps, sources and cost)."++ },++ "idempotency_key": {++ "type": "string",++ "pattern": "^[A-Za-z0-9_.:-]{1,128}$",++ "description": "The caller's id for this result (Actor: the run's task id): sent again, it is posted once."++ }++ }++}nnew file mode 100644@@@ -0,0 +1,28 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/chat/vibe-deliver-result.v1.json",++ "title": "ChatVibeDeliverResult",++ "description": "chat.vibe-deliver-result@1: where a chat.vibe-deliver-request@1 was posted. `repeated` is true when the idempotency key was seen before (nothing was posted again).",++ "type": "object",++ "required": [++ "chat",++ "url",++ "repeated"++ ],++ "additionalProperties": false,++ "properties": {++ "chat": {++ "type": "string",++ "pattern": "^v-[0-9a-f]{12}$",++ "description": "The Vibe chat's slug."++ },++ "url": {++ "type": "string",++ "format": "uri",++ "pattern": "^https://"++ },++ "repeated": {++ "type": "boolean"++ }++ }++}nnew file mode 100644@@@ -0,0 +1,8 @@++{++ "subject": "usr_01JABCDEFGHJKMNPQRSTVWXYZ0",++ "source": {++ "kind": "agent",++ "id": "agt_01JABCDEFGHJKMNPQRSTVWXYZ1"++ },++ "text": "Done."++}nnew file mode 100644@@@ -0,0 +1,9 @@++{++ "subject": "usr_01JABCDEFGHJKMNPQRSTVWXYZ0",++ "source": {++ "kind": "voice",++ "id": "dev_1"++ },++ "text": "Done.",++ "idempotency_key": "k1"++}nnew file mode 100644@@@ -0,0 +1,11 @@++{++ "subject": "usr_01JABCDEFGHJKMNPQRSTVWXYZ0",++ "source": {++ "kind": "agent",++ "id": "agt_01JABCDEFGHJKMNPQRSTVWXYZ1",++ "name": "Remote jobs"++ },++ "text": "**3 new remote video editing jobs** today:\n\n- [Editor at Example](https://example.com/jobs/1)",++ "url": "https://openvibe.actor/tasks/tsk_01JABCDEFGHJKMNPQRSTVWXYZ2",++ "idempotency_key": "agent-run-0001"++}nnew file mode 100644@@@ -0,0 +1,4 @@++{++ "chat": "v-0123456789ab",++ "url": "https://openvibe.chat/vibe/v-0123456789ab"++}nnew file mode 100644@@@ -0,0 +1,5 @@++{++ "chat": "v-0123456789ab",++ "url": "https://openvibe.chat/vibe/v-0123456789ab",++ "repeated": false++}@@@ -56475,6 +56475,107 @@}}},++ "chat.vibe-deliver-request": {++ "version": "1.0.0",++ "owner": "chat",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/chat/vibe-deliver-request.v1.json",++ "title": "ChatVibeDeliverRequest",++ "description": "chat.vibe-deliver-request@1: a first-party service puts a result of the person's own work into their Vibe chats (OpenVibe.Actor: each finished run of one of their OpenVibe Agents, when the agent sends its results to Vibe). Chat keeps one chat per source, named after it, and posts the text there as Vibe's message, so each run is a chat they can open and continue. No AI answer is made and nothing counts against their allowance. POST /internal/chat/vibe/deliver, capability chat.vibe.deliver, loopback only.",++ "type": "object",++ "required": [++ "subject",++ "source",++ "text",++ "idempotency_key"++ ],++ "additionalProperties": false,++ "properties": {++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "The person whose work it is, as the calling service vouches (Actor: the agent's owner)."++ },++ "source": {++ "type": "object",++ "required": [++ "kind",++ "id"++ ],++ "additionalProperties": false,++ "properties": {++ "kind": {++ "enum": [++ "agent"++ ]++ },++ "id": {++ "type": "string",++ "pattern": "^[A-Za-z0-9_.:-]{1,64}$",++ "description": "The source's stable id (the agent's agt_ id): one chat per source."++ },++ "name": {++ "type": "string",++ "maxLength": 80,++ "description": "What to call it in the chat's name (the agent's name)."++ }++ }++ },++ "text": {++ "type": "string",++ "minLength": 1,++ "maxLength": 8000,++ "description": "The result, in Markdown (as Vibe's answers are shown)."++ },++ "url": {++ "type": "string",++ "format": "uri",++ "pattern": "^https://",++ "description": "Where the whole run is (its steps, sources and cost)."++ },++ "idempotency_key": {++ "type": "string",++ "pattern": "^[A-Za-z0-9_.:-]{1,128}$",++ "description": "The caller's id for this result (Actor: the run's task id): sent again, it is posted once."++ }++ }++ }++ },++ "chat.vibe-deliver-result": {++ "version": "1.0.0",++ "owner": "chat",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/chat/vibe-deliver-result.v1.json",++ "title": "ChatVibeDeliverResult",++ "description": "chat.vibe-deliver-result@1: where a chat.vibe-deliver-request@1 was posted. `repeated` is true when the idempotency key was seen before (nothing was posted again).",++ "type": "object",++ "required": [++ "chat",++ "url",++ "repeated"++ ],++ "additionalProperties": false,++ "properties": {++ "chat": {++ "type": "string",++ "pattern": "^v-[0-9a-f]{12}$",++ "description": "The Vibe chat's slug."++ },++ "url": {++ "type": "string",++ "format": "uri",++ "pattern": "^https://"++ },++ "repeated": {++ "type": "boolean"++ }++ }++ }++ },"live.moderation.action": {"version": "1.0.0","owner": "live",@@@ -76945,7 +77046,7 @@"$schema": "https://json-schema.org/draft/2020-12/schema","$id": "https://openvibe.network/contracts/actor/agent-manage-request.v1.json","title": "ActorAgentManageRequest",-- "description": "actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.",++ "description": "actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, send_to_vibe?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.","anyOf": [{"type": "object",@@@ -77021,6 +77122,10 @@"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$","description": "HH:MM UTC: quiet hours end."},++ "send_to_vibe": {++ "type": "boolean",++ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."++ },"status": {"enum": ["active",@@@ -77152,6 +77257,10 @@"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$","description": "HH:MM UTC: quiet hours end."},++ "send_to_vibe": {++ "type": "boolean",++ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."++ },"status": {"enum": ["active",@@@ -77319,6 +77428,10 @@"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$","description": "HH:MM UTC: quiet hours end."},++ "send_to_vibe": {++ "type": "boolean",++ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."++ },"status": {"enum": ["active",@@@ -1547,7 +1547,7 @@},"actor.agent-manage-request.v1": {"title": "ActorAgentManageRequest",-- "description": "actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.",++ "description": "actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, send_to_vibe?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.","anyOf": [{"type": "object",@@@ -1623,6 +1623,10 @@"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$","description": "HH:MM UTC: quiet hours end."},++ "send_to_vibe": {++ "type": "boolean",++ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."++ },"status": {"enum": ["active",@@@ -1747,6 +1751,10 @@"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$","description": "HH:MM UTC: quiet hours end."},++ "send_to_vibe": {++ "type": "boolean",++ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."++ },"status": {"enum": ["active",@@@ -1914,6 +1922,10 @@"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$","description": "HH:MM UTC: quiet hours end."},++ "send_to_vibe": {++ "type": "boolean",++ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."++ },"status": {"enum": ["active",@@@ -4139,6 +4139,62 @@}}},++ "/internal/chat/vibe/deliver": {++ "post": {++ "operationId": "post_internal_chat_vibe_deliver",++ "summary": "Put a result of a person's own work into their Vibe chats: OpenVibe.Actor posts each finished run of one of their OpenVibe Agents (one chat per agent, named after it) as Vibe's message, so each run is",++ "description": "**chat.vibe.deliver** (first-party): Put a result of a person's own work into their Vibe chats: OpenVibe.Actor posts each finished run of one of their OpenVibe Agents (one chat per agent, named after it) as Vibe's message, so each run is a chat they can open and continue. No AI answer is made and nothing counts against their allowance. Loopback only, first-party service token; never granted to an app or delegated to an agent.",++ "tags": [++ "chat.vibe"++ ],++ "x-openvibe-capabilities": [++ "chat.vibe.deliver"++ ],++ "x-openvibe-visibility": [++ "first-party"++ ],++ "x-openvibe-quota-class": "internal-write",++ "security": [++ {++ "openvibeToken": [++ "chat.vibe.deliver"++ ]++ }++ ],++ "requestBody": {++ "required": false,++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/chat.vibe-deliver-request.v1"++ }++ }++ }++ },++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/chat.vibe-deliver-result.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ }++ },"/internal/live/calls": {"post": {"operationId": "post_internal_live_calls",@@@ -8303,6 +8359,93 @@}}},++ "chat.vibe-deliver-request.v1": {++ "title": "ChatVibeDeliverRequest",++ "description": "chat.vibe-deliver-request@1: a first-party service puts a result of the person's own work into their Vibe chats (OpenVibe.Actor: each finished run of one of their OpenVibe Agents, when the agent sends its results to Vibe). Chat keeps one chat per source, named after it, and posts the text there as Vibe's message, so each run is a chat they can open and continue. No AI answer is made and nothing counts against their allowance. POST /internal/chat/vibe/deliver, capability chat.vibe.deliver, loopback only.",++ "type": "object",++ "required": [++ "subject",++ "source",++ "text",++ "idempotency_key"++ ],++ "additionalProperties": false,++ "properties": {++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "The person whose work it is, as the calling service vouches (Actor: the agent's owner)."++ },++ "source": {++ "type": "object",++ "required": [++ "kind",++ "id"++ ],++ "additionalProperties": false,++ "properties": {++ "kind": {++ "enum": [++ "agent"++ ]++ },++ "id": {++ "type": "string",++ "pattern": "^[A-Za-z0-9_.:-]{1,64}$",++ "description": "The source's stable id (the agent's agt_ id): one chat per source."++ },++ "name": {++ "type": "string",++ "maxLength": 80,++ "description": "What to call it in the chat's name (the agent's name)."++ }++ }++ },++ "text": {++ "type": "string",++ "minLength": 1,++ "maxLength": 8000,++ "description": "The result, in Markdown (as Vibe's answers are shown)."++ },++ "url": {++ "type": "string",++ "format": "uri",++ "pattern": "^https://",++ "description": "Where the whole run is (its steps, sources and cost)."++ },++ "idempotency_key": {++ "type": "string",++ "pattern": "^[A-Za-z0-9_.:-]{1,128}$",++ "description": "The caller's id for this result (Actor: the run's task id): sent again, it is posted once."++ }++ }++ },++ "chat.vibe-deliver-result.v1": {++ "title": "ChatVibeDeliverResult",++ "description": "chat.vibe-deliver-result@1: where a chat.vibe-deliver-request@1 was posted. `repeated` is true when the idempotency key was seen before (nothing was posted again).",++ "type": "object",++ "required": [++ "chat",++ "url",++ "repeated"++ ],++ "additionalProperties": false,++ "properties": {++ "chat": {++ "type": "string",++ "pattern": "^v-[0-9a-f]{12}$",++ "description": "The Vibe chat's slug."++ },++ "url": {++ "type": "string",++ "format": "uri",++ "pattern": "^https://"++ },++ "repeated": {++ "type": "boolean"++ }++ }++ },"common.owned-resource-control-request.v1": {"title": "OwnedResourceControlRequest","description": "common.owned-resource-control-request@1 (ADR-048 amendment 2026-10-15, step 8 phase 2): one control operation on a person-owned resource. Robots, chat rooms, restream definitions and pastes belong to a person, not to a project, so they carry no OVRN and the project-scoped common.resource-control-request@1 cannot name them. OpenVibe.Services sends this to the owning authority's POST /api/v1/resources/control (the same route, told apart by `owned`), acting for the person in on_behalf_of. owned names the resource by its index summary's kind and id. owner is the person it belongs to: the authority refuses unless its own record says the same (Services also offers actions only on the viewer's own resources). A sensitive action (deleting, physical control) asked by an agent is refused with confirmation_required until the owner approves, as for project resources. idempotency_key makes a retry safe: the authority answers a repeated key from the same caller with the first result, and refuses the key reused with another request. Answered with common.resource-control-result@1 (without resource: there is no OVRN). The actions each authority takes are in its <service>.resource.control capability; any other action is refused unsupported.",@@@ -40,8 +40,8 @@"service": "chat","name": "OpenVibe.Chat","origin": "https://openvibe.chat",-- "operations": 53,-- "capabilities": 18++ "operations": 54,++ "capabilities": 19},{"service": "codes",@@@ -191023,6 +191023,53 @@ export interface ChatVibeAskResult {code?: string;}++/** [email protected] (owner: chat) */++/**++ * chat.vibe-deliver-request@1: a first-party service puts a result of the person's own work into their Vibe chats (OpenVibe.Actor: each finished run of one of their OpenVibe Agents, when the agent sends its results to Vibe). Chat keeps one chat per source, named after it, and posts the text there as Vibe's message, so each run is a chat they can open and continue. No AI answer is made and nothing counts against their allowance. POST /internal/chat/vibe/deliver, capability chat.vibe.deliver, loopback only.++ */++export interface ChatVibeDeliverRequest {++ /**++ * The person whose work it is, as the calling service vouches (Actor: the agent's owner).++ */++ subject: string;++ source: {++ kind: "agent";++ /**++ * The source's stable id (the agent's agt_ id): one chat per source.++ */++ id: string;++ /**++ * What to call it in the chat's name (the agent's name).++ */++ name?: string;++ };++ /**++ * The result, in Markdown (as Vibe's answers are shown).++ */++ text: string;++ /**++ * Where the whole run is (its steps, sources and cost).++ */++ url?: string;++ /**++ * The caller's id for this result (Actor: the run's task id): sent again, it is posted once.++ */++ idempotency_key: string;++}++++/** [email protected] (owner: chat) */++/**++ * chat.vibe-deliver-result@1: where a chat.vibe-deliver-request@1 was posted. `repeated` is true when the idempotency key was seen before (nothing was posted again).++ */++export interface ChatVibeDeliverResult {++ /**++ * The Vibe chat's slug.++ */++ chat: string;++ url: string;++ repeated: boolean;++}++/** [email protected] (owner: live) *//*** live.moderation.action v1 (OpenVibe.Live server/db/database.js logModerationAction; ADR-022). A staff or channel moderator action taken on OpenVibe.Live outside chat: site and global bans, IP bans, message deletes and purges from Live's admin panel, a stream force-ended, relay users hidden, channel moderators added or removed. Not a person tidying their own messages or configuring their own channel. Written to Live's outbox in the transaction that records the action. OpenVibe.Network keeps it in the moderation audit log. Envelope: subject { type: moderation_action, id: <action_id> }, visibility internal, actor the acting person when known. details is free-form per action (never secrets or message text beyond what moderators saw).@@@ -200433,7 +200480,7 @@ export interface ActorTaskCreateRequest {/** [email protected] (owner: actor) *//**-- * actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.++ * actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, send_to_vibe?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.*/export type ActorAgentManageRequest =| {@@@ -200462,6 +200509,10 @@ export type ActorAgentManageRequest =* HH:MM UTC: quiet hours end.*/quiet_to?: string | null;++ /**++ * Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true.++ */++ send_to_vibe?: boolean;status?: "active" | "paused";}| {@@@ -200502,6 +200553,10 @@ export type ActorAgentManageResult =* HH:MM UTC: quiet hours end.*/quiet_to?: string | null;++ /**++ * Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true.++ */++ send_to_vibe?: boolean;status: "active" | "paused";next_run_at?: string | null;last_run_at?: string | null;@@@ -200548,6 +200603,10 @@ export type ActorAgentManageResult =* HH:MM UTC: quiet hours end.*/quiet_to?: string | null;++ /**++ * Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true.++ */++ send_to_vibe?: boolean;status: "active" | "paused";next_run_at?: string | null;last_run_at?: string | null;nnew file mode 100644@@@ -0,0 +1,22 @@++{++ "id": "chat.vibe.deliver",++ "version": "1.0",++ "owner": "chat",++ "status": "active",++ "visibility": "first-party",++ "sensitive": true,++ "description": "Put a result of a person's own work into their Vibe chats: OpenVibe.Actor posts each finished run of one of their OpenVibe Agents (one chat per agent, named after it) as Vibe's message, so each run is a chat they can open and continue. No AI answer is made and nothing counts against their allowance. Loopback only, first-party service token; never granted to an app or delegated to an agent.",++ "permissions": [++ "chat:write"++ ],++ "resourceConstraints": [++ "none"++ ],++ "quotaClass": "internal-write",++ "events": [],++ "implementedBy": [++ "POST /internal/chat/vibe/deliver"++ ],++ "inputSchema": "chat.vibe-deliver-request@1",++ "outputSchema": "chat.vibe-deliver-result@1"++}@@@ -31,7 +31,8 @@"chat.inbox.read","chat.inbox.reply","chat.inbox.manage",-- "chat.vibe.ask"++ "chat.vibe.ask",++ "chat.vibe.deliver"],"eventsProduced": ["chat.message.created",
@@ -6,6 +6,13 @@ the notes were in the tag and commit messages (`git tag -n1`).
@@ -6,6 +6,13 @@ the notes were in the tag and commit messages (`git tag -n1`).
## 0.214.0 — 2026-10-26
## 0.214.0 — 2026-10-26
+- **`chat.vibe.deliver`** (first-party, sensitive, owned by `chat`; consumer plan §4: "each run is a chat you can
+ open"): a first-party service puts a result of the person's own work into their Vibe chats (`POST
+ /internal/chat/vibe/deliver`). OpenVibe.Actor posts each finished run of one of their OpenVibe Agents into one chat per
+ agent, named after it, as Vibe's message. No AI answer is made and nothing counts against the allowance. Schemas
+ `chat.vibe-deliver-request@1` (subject, source { kind agent, id, name }, text in Markdown, url, idempotency_key) and
+ `chat.vibe-deliver-result@1` (chat, url, repeated), with fixtures. `actor.agent-manage-request@1` and `-result@1`
+ gain `send_to_vibe` (boolean, default true), the agent's switch for it.
- **`actor.agent.manage`** lists the suggestions routes (`GET /api/v1/me/agents/:id/suggestions`, `POST
- **`actor.agent.manage`** lists the suggestions routes (`GET /api/v1/me/agents/:id/suggestions`, `POST
…/suggestions/:pid/:action` with apply | dismiss | undo): a personal agent may suggest a line for its instructions after a
…/suggestions/:pid/:action` with apply | dismiss | undo): a personal agent may suggest a line for its instructions after a
run that passed its check, which waits for the person (OpenVibe.Actor#115).
run that passed its check, which waits for the person (OpenVibe.Actor#115).
@@ -2,7 +2,7 @@
@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://openvibe.network/contracts/actor/agent-manage-request.v1.json",
"$id": "https://openvibe.network/contracts/actor/agent-manage-request.v1.json",
"title": "ActorAgentManageRequest",
"title": "ActorAgentManageRequest",
- "description": "actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.",
+ "description": "actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, send_to_vibe?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.",
"anyOf": [
"anyOf": [
{
{
"type": "object",
"type": "object",
@@ -78,6 +78,10 @@
@@ -78,6 +78,10 @@
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"description": "HH:MM UTC: quiet hours end."
"description": "HH:MM UTC: quiet hours end."
},
},
+ "send_to_vibe": {
+ "type": "boolean",
+ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."
+ },
"status": {
"status": {
"enum": [
"enum": [
"active",
"active",
@@ -100,6 +100,10 @@
@@ -100,6 +100,10 @@
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"description": "HH:MM UTC: quiet hours end."
"description": "HH:MM UTC: quiet hours end."
},
},
+ "send_to_vibe": {
+ "type": "boolean",
+ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."
+ },
"status": {
"status": {
"enum": [
"enum": [
"active",
"active",
@@ -267,6 +271,10 @@
@@ -267,6 +271,10 @@
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"description": "HH:MM UTC: quiet hours end."
"description": "HH:MM UTC: quiet hours end."
},
},
+ "send_to_vibe": {
+ "type": "boolean",
+ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."
+ },
"status": {
"status": {
"enum": [
"enum": [
"active",
"active",
@@ -5096,6 +5096,24 @@
@@ -5096,6 +5096,24 @@
"compatibility": "backward",
"compatibility": "backward",
"status": "active"
"status": "active"
},
},
+ {
+ "id": "chat.vibe-deliver-request",
+ "version": "1.0.0",
+ "owner": "chat",
+ "schema": "chat/vibe-deliver-request.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active"
+ },
+ {
+ "id": "chat.vibe-deliver-result",
+ "version": "1.0.0",
+ "owner": "chat",
+ "schema": "chat/vibe-deliver-result.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active"
+ },
{
{
"id": "live.moderation.action",
"id": "live.moderation.action",
"version": "1.0.0",
"version": "1.0.0",
new file mode 100644
new file mode 100644
@@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/chat/vibe-deliver-request.v1.json",
+ "title": "ChatVibeDeliverRequest",
+ "description": "chat.vibe-deliver-request@1: a first-party service puts a result of the person's own work into their Vibe chats (OpenVibe.Actor: each finished run of one of their OpenVibe Agents, when the agent sends its results to Vibe). Chat keeps one chat per source, named after it, and posts the text there as Vibe's message, so each run is a chat they can open and continue. No AI answer is made and nothing counts against their allowance. POST /internal/chat/vibe/deliver, capability chat.vibe.deliver, loopback only.",
+ "type": "object",
+ "required": [
+ "subject",
+ "source",
+ "text",
+ "idempotency_key"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "The person whose work it is, as the calling service vouches (Actor: the agent's owner)."
+ },
+ "source": {
+ "type": "object",
+ "required": [
+ "kind",
+ "id"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "kind": {
+ "enum": [
+ "agent"
+ ]
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[A-Za-z0-9_.:-]{1,64}$",
+ "description": "The source's stable id (the agent's agt_ id): one chat per source."
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 80,
+ "description": "What to call it in the chat's name (the agent's name)."
+ }
+ }
+ },
+ "text": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 8000,
+ "description": "The result, in Markdown (as Vibe's answers are shown)."
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https://",
+ "description": "Where the whole run is (its steps, sources and cost)."
+ },
+ "idempotency_key": {
+ "type": "string",
+ "pattern": "^[A-Za-z0-9_.:-]{1,128}$",
+ "description": "The caller's id for this result (Actor: the run's task id): sent again, it is posted once."
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/chat/vibe-deliver-result.v1.json",
+ "title": "ChatVibeDeliverResult",
+ "description": "chat.vibe-deliver-result@1: where a chat.vibe-deliver-request@1 was posted. `repeated` is true when the idempotency key was seen before (nothing was posted again).",
+ "type": "object",
+ "required": [
+ "chat",
+ "url",
+ "repeated"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "chat": {
+ "type": "string",
+ "pattern": "^v-[0-9a-f]{12}$",
+ "description": "The Vibe chat's slug."
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https://"
+ },
+ "repeated": {
+ "type": "boolean"
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
+{
+ "subject": "usr_01JABCDEFGHJKMNPQRSTVWXYZ0",
+ "source": {
+ "kind": "agent",
+ "id": "agt_01JABCDEFGHJKMNPQRSTVWXYZ1"
+ },
+ "text": "Done."
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
+{
+ "subject": "usr_01JABCDEFGHJKMNPQRSTVWXYZ0",
+ "source": {
+ "kind": "voice",
+ "id": "dev_1"
+ },
+ "text": "Done.",
+ "idempotency_key": "k1"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
+{
+ "subject": "usr_01JABCDEFGHJKMNPQRSTVWXYZ0",
+ "source": {
+ "kind": "agent",
+ "id": "agt_01JABCDEFGHJKMNPQRSTVWXYZ1",
+ "name": "Remote jobs"
+ },
+ "text": "**3 new remote video editing jobs** today:\n\n- [Editor at Example](https://example.com/jobs/1)",
+ "url": "https://openvibe.actor/tasks/tsk_01JABCDEFGHJKMNPQRSTVWXYZ2",
+ "idempotency_key": "agent-run-0001"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
+{
+ "chat": "v-0123456789ab",
+ "url": "https://openvibe.chat/vibe/v-0123456789ab"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
+{
+ "chat": "v-0123456789ab",
+ "url": "https://openvibe.chat/vibe/v-0123456789ab",
+ "repeated": false
+}
@@ -56475,6 +56475,107 @@
@@ -56475,6 +56475,107 @@
}
}
}
}
},
},
+ "chat.vibe-deliver-request": {
+ "version": "1.0.0",
+ "owner": "chat",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/chat/vibe-deliver-request.v1.json",
+ "title": "ChatVibeDeliverRequest",
+ "description": "chat.vibe-deliver-request@1: a first-party service puts a result of the person's own work into their Vibe chats (OpenVibe.Actor: each finished run of one of their OpenVibe Agents, when the agent sends its results to Vibe). Chat keeps one chat per source, named after it, and posts the text there as Vibe's message, so each run is a chat they can open and continue. No AI answer is made and nothing counts against their allowance. POST /internal/chat/vibe/deliver, capability chat.vibe.deliver, loopback only.",
+ "type": "object",
+ "required": [
+ "subject",
+ "source",
+ "text",
+ "idempotency_key"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "The person whose work it is, as the calling service vouches (Actor: the agent's owner)."
+ },
+ "source": {
+ "type": "object",
+ "required": [
+ "kind",
+ "id"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "kind": {
+ "enum": [
+ "agent"
+ ]
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[A-Za-z0-9_.:-]{1,64}$",
+ "description": "The source's stable id (the agent's agt_ id): one chat per source."
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 80,
+ "description": "What to call it in the chat's name (the agent's name)."
+ }
+ }
+ },
+ "text": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 8000,
+ "description": "The result, in Markdown (as Vibe's answers are shown)."
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https://",
+ "description": "Where the whole run is (its steps, sources and cost)."
+ },
+ "idempotency_key": {
+ "type": "string",
+ "pattern": "^[A-Za-z0-9_.:-]{1,128}$",
+ "description": "The caller's id for this result (Actor: the run's task id): sent again, it is posted once."
+ }
+ }
+ }
+ },
+ "chat.vibe-deliver-result": {
+ "version": "1.0.0",
+ "owner": "chat",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/chat/vibe-deliver-result.v1.json",
+ "title": "ChatVibeDeliverResult",
+ "description": "chat.vibe-deliver-result@1: where a chat.vibe-deliver-request@1 was posted. `repeated` is true when the idempotency key was seen before (nothing was posted again).",
+ "type": "object",
+ "required": [
+ "chat",
+ "url",
+ "repeated"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "chat": {
+ "type": "string",
+ "pattern": "^v-[0-9a-f]{12}$",
+ "description": "The Vibe chat's slug."
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https://"
+ },
+ "repeated": {
+ "type": "boolean"
+ }
+ }
+ }
+ },
"live.moderation.action": {
"live.moderation.action": {
"version": "1.0.0",
"version": "1.0.0",
"owner": "live",
"owner": "live",
@@ -76945,7 +77046,7 @@
@@ -76945,7 +77046,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://openvibe.network/contracts/actor/agent-manage-request.v1.json",
"$id": "https://openvibe.network/contracts/actor/agent-manage-request.v1.json",
"title": "ActorAgentManageRequest",
"title": "ActorAgentManageRequest",
- "description": "actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.",
+ "description": "actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, send_to_vibe?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.",
"anyOf": [
"anyOf": [
{
{
"type": "object",
"type": "object",
@@ -77021,6 +77122,10 @@
@@ -77021,6 +77122,10 @@
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"description": "HH:MM UTC: quiet hours end."
"description": "HH:MM UTC: quiet hours end."
},
},
+ "send_to_vibe": {
+ "type": "boolean",
+ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."
+ },
"status": {
"status": {
"enum": [
"enum": [
"active",
"active",
@@ -77152,6 +77257,10 @@
@@ -77152,6 +77257,10 @@
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"description": "HH:MM UTC: quiet hours end."
"description": "HH:MM UTC: quiet hours end."
},
},
+ "send_to_vibe": {
+ "type": "boolean",
+ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."
+ },
"status": {
"status": {
"enum": [
"enum": [
"active",
"active",
@@ -77319,6 +77428,10 @@
@@ -77319,6 +77428,10 @@
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"description": "HH:MM UTC: quiet hours end."
"description": "HH:MM UTC: quiet hours end."
},
},
+ "send_to_vibe": {
+ "type": "boolean",
+ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."
+ },
"status": {
"status": {
"enum": [
"enum": [
"active",
"active",
@@ -1547,7 +1547,7 @@
@@ -1547,7 +1547,7 @@
},
},
"actor.agent-manage-request.v1": {
"actor.agent-manage-request.v1": {
"title": "ActorAgentManageRequest",
"title": "ActorAgentManageRequest",
- "description": "actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.",
+ "description": "actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, send_to_vibe?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.",
"anyOf": [
"anyOf": [
{
{
"type": "object",
"type": "object",
@@ -1623,6 +1623,10 @@
@@ -1623,6 +1623,10 @@
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"description": "HH:MM UTC: quiet hours end."
"description": "HH:MM UTC: quiet hours end."
},
},
+ "send_to_vibe": {
+ "type": "boolean",
+ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."
+ },
"status": {
"status": {
"enum": [
"enum": [
"active",
"active",
@@ -1747,6 +1751,10 @@
@@ -1747,6 +1751,10 @@
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"description": "HH:MM UTC: quiet hours end."
"description": "HH:MM UTC: quiet hours end."
},
},
+ "send_to_vibe": {
+ "type": "boolean",
+ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."
+ },
"status": {
"status": {
"enum": [
"enum": [
"active",
"active",
@@ -1914,6 +1922,10 @@
@@ -1914,6 +1922,10 @@
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
"description": "HH:MM UTC: quiet hours end."
"description": "HH:MM UTC: quiet hours end."
},
},
+ "send_to_vibe": {
+ "type": "boolean",
+ "description": "Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true."
+ },
"status": {
"status": {
"enum": [
"enum": [
"active",
"active",
@@ -4139,6 +4139,62 @@
@@ -4139,6 +4139,62 @@
}
}
}
}
},
},
+ "/internal/chat/vibe/deliver": {
+ "post": {
+ "operationId": "post_internal_chat_vibe_deliver",
+ "summary": "Put a result of a person's own work into their Vibe chats: OpenVibe.Actor posts each finished run of one of their OpenVibe Agents (one chat per agent, named after it) as Vibe's message, so each run is",
+ "description": "**chat.vibe.deliver** (first-party): Put a result of a person's own work into their Vibe chats: OpenVibe.Actor posts each finished run of one of their OpenVibe Agents (one chat per agent, named after it) as Vibe's message, so each run is a chat they can open and continue. No AI answer is made and nothing counts against their allowance. Loopback only, first-party service token; never granted to an app or delegated to an agent.",
+ "tags": [
+ "chat.vibe"
+ ],
+ "x-openvibe-capabilities": [
+ "chat.vibe.deliver"
+ ],
+ "x-openvibe-visibility": [
+ "first-party"
+ ],
+ "x-openvibe-quota-class": "internal-write",
+ "security": [
+ {
+ "openvibeToken": [
+ "chat.vibe.deliver"
+ ]
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/chat.vibe-deliver-request.v1"
+ }
+ }
+ }
+ },
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/chat.vibe-deliver-result.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"/internal/live/calls": {
"/internal/live/calls": {
"post": {
"post": {
"operationId": "post_internal_live_calls",
"operationId": "post_internal_live_calls",
@@ -8303,6 +8359,93 @@
@@ -8303,6 +8359,93 @@
}
}
}
}
},
},
+ "chat.vibe-deliver-request.v1": {
+ "title": "ChatVibeDeliverRequest",
+ "description": "chat.vibe-deliver-request@1: a first-party service puts a result of the person's own work into their Vibe chats (OpenVibe.Actor: each finished run of one of their OpenVibe Agents, when the agent sends its results to Vibe). Chat keeps one chat per source, named after it, and posts the text there as Vibe's message, so each run is a chat they can open and continue. No AI answer is made and nothing counts against their allowance. POST /internal/chat/vibe/deliver, capability chat.vibe.deliver, loopback only.",
+ "type": "object",
+ "required": [
+ "subject",
+ "source",
+ "text",
+ "idempotency_key"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "The person whose work it is, as the calling service vouches (Actor: the agent's owner)."
+ },
+ "source": {
+ "type": "object",
+ "required": [
+ "kind",
+ "id"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "kind": {
+ "enum": [
+ "agent"
+ ]
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[A-Za-z0-9_.:-]{1,64}$",
+ "description": "The source's stable id (the agent's agt_ id): one chat per source."
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 80,
+ "description": "What to call it in the chat's name (the agent's name)."
+ }
+ }
+ },
+ "text": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 8000,
+ "description": "The result, in Markdown (as Vibe's answers are shown)."
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https://",
+ "description": "Where the whole run is (its steps, sources and cost)."
+ },
+ "idempotency_key": {
+ "type": "string",
+ "pattern": "^[A-Za-z0-9_.:-]{1,128}$",
+ "description": "The caller's id for this result (Actor: the run's task id): sent again, it is posted once."
+ }
+ }
+ },
+ "chat.vibe-deliver-result.v1": {
+ "title": "ChatVibeDeliverResult",
+ "description": "chat.vibe-deliver-result@1: where a chat.vibe-deliver-request@1 was posted. `repeated` is true when the idempotency key was seen before (nothing was posted again).",
+ "type": "object",
+ "required": [
+ "chat",
+ "url",
+ "repeated"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "chat": {
+ "type": "string",
+ "pattern": "^v-[0-9a-f]{12}$",
+ "description": "The Vibe chat's slug."
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https://"
+ },
+ "repeated": {
+ "type": "boolean"
+ }
+ }
+ },
"common.owned-resource-control-request.v1": {
"common.owned-resource-control-request.v1": {
"title": "OwnedResourceControlRequest",
"title": "OwnedResourceControlRequest",
"description": "common.owned-resource-control-request@1 (ADR-048 amendment 2026-10-15, step 8 phase 2): one control operation on a person-owned resource. Robots, chat rooms, restream definitions and pastes belong to a person, not to a project, so they carry no OVRN and the project-scoped common.resource-control-request@1 cannot name them. OpenVibe.Services sends this to the owning authority's POST /api/v1/resources/control (the same route, told apart by `owned`), acting for the person in on_behalf_of. owned names the resource by its index summary's kind and id. owner is the person it belongs to: the authority refuses unless its own record says the same (Services also offers actions only on the viewer's own resources). A sensitive action (deleting, physical control) asked by an agent is refused with confirmation_required until the owner approves, as for project resources. idempotency_key makes a retry safe: the authority answers a repeated key from the same caller with the first result, and refuses the key reused with another request. Answered with common.resource-control-result@1 (without resource: there is no OVRN). The actions each authority takes are in its <service>.resource.control capability; any other action is refused unsupported.",
"description": "common.owned-resource-control-request@1 (ADR-048 amendment 2026-10-15, step 8 phase 2): one control operation on a person-owned resource. Robots, chat rooms, restream definitions and pastes belong to a person, not to a project, so they carry no OVRN and the project-scoped common.resource-control-request@1 cannot name them. OpenVibe.Services sends this to the owning authority's POST /api/v1/resources/control (the same route, told apart by `owned`), acting for the person in on_behalf_of. owned names the resource by its index summary's kind and id. owner is the person it belongs to: the authority refuses unless its own record says the same (Services also offers actions only on the viewer's own resources). A sensitive action (deleting, physical control) asked by an agent is refused with confirmation_required until the owner approves, as for project resources. idempotency_key makes a retry safe: the authority answers a repeated key from the same caller with the first result, and refuses the key reused with another request. Answered with common.resource-control-result@1 (without resource: there is no OVRN). The actions each authority takes are in its <service>.resource.control capability; any other action is refused unsupported.",
@@ -40,8 +40,8 @@
@@ -40,8 +40,8 @@
"service": "chat",
"service": "chat",
"name": "OpenVibe.Chat",
"name": "OpenVibe.Chat",
"origin": "https://openvibe.chat",
"origin": "https://openvibe.chat",
- "operations": 53,
- "capabilities": 18
+ "operations": 54,
+ "capabilities": 19
},
},
{
{
"service": "codes",
"service": "codes",
@@ -191023,6 +191023,53 @@ export interface ChatVibeAskResult {
@@ -191023,6 +191023,53 @@ export interface ChatVibeAskResult {
code?: string;
code?: string;
}
}
+/** [email protected] (owner: chat) */
+/**
+ * chat.vibe-deliver-request@1: a first-party service puts a result of the person's own work into their Vibe chats (OpenVibe.Actor: each finished run of one of their OpenVibe Agents, when the agent sends its results to Vibe). Chat keeps one chat per source, named after it, and posts the text there as Vibe's message, so each run is a chat they can open and continue. No AI answer is made and nothing counts against their allowance. POST /internal/chat/vibe/deliver, capability chat.vibe.deliver, loopback only.
+ */
+export interface ChatVibeDeliverRequest {
+ /**
+ * The person whose work it is, as the calling service vouches (Actor: the agent's owner).
+ */
+ subject: string;
+ source: {
+ kind: "agent";
+ /**
+ * The source's stable id (the agent's agt_ id): one chat per source.
+ */
+ id: string;
+ /**
+ * What to call it in the chat's name (the agent's name).
+ */
+ name?: string;
+ };
+ /**
+ * The result, in Markdown (as Vibe's answers are shown).
+ */
+ text: string;
+ /**
+ * Where the whole run is (its steps, sources and cost).
+ */
+ url?: string;
+ /**
+ * The caller's id for this result (Actor: the run's task id): sent again, it is posted once.
+ */
+ idempotency_key: string;
+}
+
+/** [email protected] (owner: chat) */
+/**
+ * chat.vibe-deliver-result@1: where a chat.vibe-deliver-request@1 was posted. `repeated` is true when the idempotency key was seen before (nothing was posted again).
+ */
+export interface ChatVibeDeliverResult {
+ /**
+ * The Vibe chat's slug.
+ */
+ chat: string;
+ url: string;
+ repeated: boolean;
+}
+
/** [email protected] (owner: live) */
/** [email protected] (owner: live) */
/**
/**
* live.moderation.action v1 (OpenVibe.Live server/db/database.js logModerationAction; ADR-022). A staff or channel moderator action taken on OpenVibe.Live outside chat: site and global bans, IP bans, message deletes and purges from Live's admin panel, a stream force-ended, relay users hidden, channel moderators added or removed. Not a person tidying their own messages or configuring their own channel. Written to Live's outbox in the transaction that records the action. OpenVibe.Network keeps it in the moderation audit log. Envelope: subject { type: moderation_action, id: <action_id> }, visibility internal, actor the acting person when known. details is free-form per action (never secrets or message text beyond what moderators saw).
* live.moderation.action v1 (OpenVibe.Live server/db/database.js logModerationAction; ADR-022). A staff or channel moderator action taken on OpenVibe.Live outside chat: site and global bans, IP bans, message deletes and purges from Live's admin panel, a stream force-ended, relay users hidden, channel moderators added or removed. Not a person tidying their own messages or configuring their own channel. Written to Live's outbox in the transaction that records the action. OpenVibe.Network keeps it in the moderation audit log. Envelope: subject { type: moderation_action, id: <action_id> }, visibility internal, actor the acting person when known. details is free-form per action (never secrets or message text beyond what moderators saw).
@@ -200433,7 +200480,7 @@ export interface ActorTaskCreateRequest {
@@ -200433,7 +200480,7 @@ export interface ActorTaskCreateRequest {
/** [email protected] (owner: actor) */
/** [email protected] (owner: actor) */
/**
/**
- * actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.
+ * actor.agent-manage-request@1: bodies of actor.agent.manage on OpenVibe.Actor. POST /api/v1/me/agents { name, instructions, mode?, budget_per_run_usd?, daily_runs_max?, schedule?, schedule_at?, schedule_dow?, quiet_from?, quiet_to?, send_to_vibe?, status? } creates a personal agent (10 per person: 429 actor.agent.limit); PATCH /api/v1/me/agents/:id takes any subset. POST /api/v1/me/agents/:id/memory { text } adds a note (1–1000 characters; 50 notes, the oldest agent-written note goes first, a person's note never automatically) and PATCH /api/v1/me/agents/:id/memory/:mem { text } edits one. Unknown fields are 422 actor.agent.invalid; another person's agent is 404 actor.agent.not_found.
*/
*/
export type ActorAgentManageRequest =
export type ActorAgentManageRequest =
| {
| {
@@ -200462,6 +200509,10 @@ export type ActorAgentManageRequest =
@@ -200462,6 +200509,10 @@ export type ActorAgentManageRequest =
* HH:MM UTC: quiet hours end.
* HH:MM UTC: quiet hours end.
*/
*/
quiet_to?: string | null;
quiet_to?: string | null;
+ /**
+ * Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true.
+ */
+ send_to_vibe?: boolean;
status?: "active" | "paused";
status?: "active" | "paused";
}
}
| {
| {
@@ -200502,6 +200553,10 @@ export type ActorAgentManageResult =
@@ -200502,6 +200553,10 @@ export type ActorAgentManageResult =
* HH:MM UTC: quiet hours end.
* HH:MM UTC: quiet hours end.
*/
*/
quiet_to?: string | null;
quiet_to?: string | null;
+ /**
+ * Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true.
+ */
+ send_to_vibe?: boolean;
status: "active" | "paused";
status: "active" | "paused";
next_run_at?: string | null;
next_run_at?: string | null;
last_run_at?: string | null;
last_run_at?: string | null;
@@ -200548,6 +200603,10 @@ export type ActorAgentManageResult =
@@ -200548,6 +200603,10 @@ export type ActorAgentManageResult =
* HH:MM UTC: quiet hours end.
* HH:MM UTC: quiet hours end.
*/
*/
quiet_to?: string | null;
quiet_to?: string | null;
+ /**
+ * Post each finished run into the person's own Vibe chat named after the agent (chat.vibe.deliver), so each run is a chat they can open and continue. Default true.
+ */
+ send_to_vibe?: boolean;
status: "active" | "paused";
status: "active" | "paused";
next_run_at?: string | null;
next_run_at?: string | null;
last_run_at?: string | null;
last_run_at?: string | null;
new file mode 100644
new file mode 100644
@@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
+{
+ "id": "chat.vibe.deliver",
+ "version": "1.0",
+ "owner": "chat",
+ "status": "active",
+ "visibility": "first-party",
+ "sensitive": true,
+ "description": "Put a result of a person's own work into their Vibe chats: OpenVibe.Actor posts each finished run of one of their OpenVibe Agents (one chat per agent, named after it) as Vibe's message, so each run is a chat they can open and continue. No AI answer is made and nothing counts against their allowance. Loopback only, first-party service token; never granted to an app or delegated to an agent.",
+ "permissions": [
+ "chat:write"
+ ],
+ "resourceConstraints": [
+ "none"
+ ],
+ "quotaClass": "internal-write",
+ "events": [],
+ "implementedBy": [
+ "POST /internal/chat/vibe/deliver"
+ ],
+ "inputSchema": "chat.vibe-deliver-request@1",
+ "outputSchema": "chat.vibe-deliver-result@1"
+}
@@ -31,7 +31,8 @@
@@ -31,7 +31,8 @@
"chat.inbox.read",
"chat.inbox.read",
"chat.inbox.reply",
"chat.inbox.reply",
"chat.inbox.manage",
"chat.inbox.manage",
- "chat.vibe.ask"
+ "chat.vibe.ask",
+ "chat.vibe.deliver"
],
],
"eventsProduced": [
"eventsProduced": [
"chat.message.created",
"chat.message.created",