openvibers/openvibe.actor CHANGELOG.md
CHANGELOG.md
| 1 | # Changelog |
| 2 | |
| 3 | |
| 4 | ## Unreleased — agents have souls |
| 5 | |
| 6 | - **A soul** (`agents.soul@1`, Contracts 0.424.0; `openvibe-sdk/agents/soul` 0.165.0; migration 0072): who a personal |
| 7 | agent is, kept apart from its instructions and its memory. `actor_agents.soul` is jsonb (null: no soul yet); a create |
| 8 | and a patch take a `soul` that the SDK validates, and a catalogue answer carries it back with its `soul_md`. |
| 9 | - **The prompt:** a soul is the first block of a personal agent's prompt (`toPrompt(soul, { name })`) and the first |
| 10 | prompt layer, before the person's instructions, so the cached prefix stays stable. It says who the agent is, never |
| 11 | what it may do. |
| 12 | - **Import:** `POST /api/v1/agents/:id/soul/import` takes a `SOUL.md` of at most 20 KB and stores what |
| 13 | `fromSoulMd` reads; an invalid result (a secret, a bad part) is 422. |
| 14 | - **Suggestions (Design rule 176):** `POST /api/v1/agents/:id/soul/suggest` waits in `actor_agent_proposals` as kind |
| 15 | `soul` with `change()`'s words; the person accepts or dismisses it on the existing suggestions route. An agent never |
| 16 | writes its own soul. |
| 17 | - **Your agents in the menu:** `GET /api/v1/me/agents/faces` answers each face's name, avatar, hue, glyph, state |
| 18 | (working, asks, paused, resting), current step and number of asks, newest activity first and at most twelve; the |
| 19 | same first-party CORS as the Actor strip, cached privately for 15 seconds. |
| 20 | - Pins: openvibe-contracts v0.424.0, openvibe-sdk v0.165.0. |
| 21 | |
| 22 | ## Unreleased — every AI call measured |
| 23 | |
| 24 | - **AI meter** (`openvibe-sdk/ai-meter`, SDK 0.164.0): every model call Actor makes straight to a provider is recorded |
| 25 | and sent to OpenVibe.AI's `POST /api/v1/usage/calls` (a call through OpenVibe.AI, with a person's own key or the |
| 26 | router, is recorded by AI itself, so it is never counted twice): provider, |
| 27 | model, task and call id, TTFT, tokens per second, latency, tokens, tool calls, the outcome, a failure's class, and |
| 28 | the task's wall time on its last step. Actor's service token is narrowed to `ai.usage.report`. The meter is off in |
| 29 | a drill and in tests, and it never fails or blocks a model call. |
| 30 | - Pins: openvibe-contracts v0.421.0, openvibe-sdk v0.164.0. |
| 31 | |
| 32 | ## Unreleased — make your own agent (blueprints) |
| 33 | |
| 34 | - **Blueprints** (`agents.blueprint@1`, Contracts 0.419.0): a person's agent as one document of ten parts. |
| 35 | - `POST /api/v1/blueprints` makes a draft, checked against the schema and `openvibe-sdk/agents/blueprint`'s rules; |
| 36 | a blueprint carries no secret. |
| 37 | - `PUT …/:id/draft` edits it, and `POST …/:id/publish` freezes it as version N. A published version never |
| 38 | changes. |
| 39 | - `GET /api/v1/blueprints` lists mine (`?scope=public` lists the gallery), and `GET …/:id?version=N` reads one |
| 40 | version. |
| 41 | - `POST …/:id/remix` makes a private copy that credits its source, only when the author named a licence. |
| 42 | - **Installs** (`agents.install@1`): |
| 43 | - `GET …/:id/asks` is the install screen in words. |
| 44 | - `POST …/:id/install` makes the person's own agent once every ask is agreed and the inputs are filled. Its |
| 45 | instructions carry the inputs and the floor in words. |
| 46 | - When a version is published, an install set to `same-or-less` takes it if it asks for no more. Any other install |
| 47 | keeps it `pending`. |
| 48 | - `POST /api/v1/agents/:id/install/update` takes the new version once its new asks are agreed. |
| 49 | - Migration 0071 adds the blueprint, version and install tables and lets an agent's instructions run to 20,000 |
| 50 | characters. |
| 51 | - Pins: openvibe-contracts v0.419.1, openvibe-sdk v0.162.0. |
| 52 | |
| 53 | ## Unreleased — Stop, not E-STOP |
| 54 | |
| 55 | - The robot tools and page copy say Stop; `list_my_robots` no longer reads a latch field. |
| 56 | |
| 57 | What changed in OpenVibe.Actor, newest first. Each site also publishes its patch notes at /updates. |
| 58 | |
| 59 | ## Unreleased — the same run shape as Codes and Run (`agents.run@1`, `agents.step@1`) |
| 60 | |
| 61 | - **`GET /api/v1/runs`** lists the person's own runs newest first (`limit`, `before`, `status`, `agent`) in the one |
| 62 | agent system's `agents.run@1` shape: owner, agent and product, parent run, budget, status, timestamps, result |
| 63 | summary and cost. A task is the run; nothing new is stored. |
| 64 | - **`GET /api/v1/runs/:id/steps?after=`** reads the task's own event log as `agents.step@1`, one entry per output |
| 65 | event, with the task event's seq as the cursor. `GET /api/v1/runs/:id` answers the same run shape when the reader |
| 66 | asks for it with `Accept: application/vnd.openvibe.agents.run+json` (what `openvibe-sdk/agents` sends) or |
| 67 | `?shape=agents.run@1`; the existing `agent.run@1` snapshot stays the default for its callers. |
| 68 | - Read-only and behind the existing `actor.task.read`/`actor.task.list`: only the person's own Network token or |
| 69 | session, and another person's run is the same 404 as one that does not exist. Actor's tables are unchanged. |
| 70 | - The field map and what does not fit (per-step cost, Actor's `needs_you`, a tool call and its result as two log |
| 71 | entries) are in OpenVibe.Contracts `docs/agents-runs.md`; the routes are in [docs/agent-runs.md](docs/agent-runs.md). |
| 72 | Tests: `test/runs-api.test.js`. |
| 73 | |
| 74 | ## Unreleased — See it work (W1): the desk, the viewer and the replay |
| 75 | |
| 76 | - **The desk tile** in a running task's card: the desk's private Live stream (started with the task's desk through Link's |
| 77 | `desk.stream` and stopped with the task), with the still at 1/s when no stream is up. Under it the latest step in |
| 78 | plain words, a ring where it last clicked, the browser page's address and where it is ("Your PC · its own desk", |
| 79 | "OpenVibe computer"). The tile pauses its stream while off screen. |
| 80 | - **The viewer** (a tap on the tile): the desk fills a phone and sits beside the steps from 900 px, with Take over, |
| 81 | Pause, Stop and Hand back. Take over takes a Run desk's live lease or makes Bot take the person's own input on a Link |
| 82 | desk (their token, mapped to desk coordinates); the agent's input is refused while they drive. Hand back takes an |
| 83 | optional note that reaches the run as the person's message. A `hand_to_person` step is an Ask that opens the viewer |
| 84 | in control. |
| 85 | - **Replay**: every computer step keeps its still and its action. A finished task's card has a timeline to scrub, and |
| 86 | each step opens the picture it saw. Typed text is redacted before it reaches the task's events, so neither the replay |
| 87 | nor the task log carries it; a click keeps only its x,y. |
| 88 | - Migration 0070 (task stills); `GET /api/v1/tasks/:id/desks`, `/desk-still`, `/replay`, the desk take-over/hand-back |
| 89 | and the person's input. Tests: `test/see-it-work.test.js`; screenshots: `test/see-it-work-shots.js`. |
| 90 | |
| 91 | ## Unreleased — the chat is the one place you use Actor (one agent system, stage 1) |
| 92 | |
| 93 | - **Composer v2** (openvibe-shared 4.215.0, the `agent` preset): the chat mounts `OpenVibeComposer.mount` with Attach, |
| 94 | Speak, the mode chip (Fast, Balanced, Best, Cheapest, Private) and the round send; files go through Actor's existing |
| 95 | path (`POST /chat` with the file as data) and their chips show the read's progress. The dashed "Attach files" box and |
| 96 | the separate model/mode controls are gone; the model lives at `/chat/model`. |
| 97 | - **Settings** (`/chat/settings`): the run defaults ("New runs: Only me … Apply to all my existing runs") moved off the |
| 98 | chat. The route (`POST /chat/defaults`) and its behaviour are unchanged. |
| 99 | - **Four suggestion chips** on an empty chat, one line each, instead of the wall of starter cards; a chat with messages |
| 100 | shows none. |
| 101 | - **The Console is folded in**: `/console` answers 301 to `/chat` (carrying `?ask=`/`?from=`), the bottom tab bar is |
| 102 | Home, Chat, Agents, and the running tasks the Console listed are the chat's "Now" strip — one line each, Stop on each, |
| 103 | hidden when nothing runs. `/me/spend` and the approvals, agents, computers and robots APIs and pages stay. |
| 104 | - **A running task is a card in the conversation** (title, state, the last steps, Stop), refreshed in place from |
| 105 | `GET /chat/turn/:id`; stopping goes through `POST /chat/:id/cancel` and returns to the chat. |
| 106 | - Migration-free. Tests: `test/one-page.test.js`, plus the updated chat, console, model, sharing, allowance and |
| 107 | self-host suites; screenshots at 390 and 1280: `test/one-page-shots.js`. |
| 108 | |
| 109 | ## Unreleased — skills that run code, sandboxed (HO8 step 3) |
| 110 | |
| 111 | - **`actor.skill@2`: code in a sandbox** (plan HO8, ADR-060; contracts 0.343.0): a sandbox skill carries one to five |
| 112 | tools and its code as ordinary `.js` text resources. The registry reads the code, never runs it, and fails a tool |
| 113 | that reads `process.env`, starts a process, worker or `vm`, writes a file, builds code at run time, requires anything |
| 114 | but Link's safe modules, carries an encoded blob or minified code, or reaches the network outside the `net` its tool |
| 115 | declares; it flags any network use, timers over 5 s and loops over input. Every finding names its tool. The |
| 116 | cross-field rules (a tool's entry is a resource, every code resource is a tool's entry, tool names are unique) are |
| 117 | checked before anything is listed. |
| 118 | - **The bytes that run are the bytes that were scanned**: publishing a sandbox skill stores each code resource as a |
| 119 | private OpenVibe.Media object under Actor's tenant and pins `{ name, media_id, sha256 }` on the |
| 120 | `actor.skill-listing@2`; `server/skills/publish` is the registry's path (a prompt skill stays `actor.skill@1`). |
| 121 | - **`skill.run`**: a new HO1 kind ("running a skill's code in a sandbox"), allowable, with the exact target |
| 122 | `<slug>@<version> <tool>` (plus ` · internet` when `net` is `public`), so "always allow" covers one version's tool. |
| 123 | - **The tool the agent calls**: each installed sandbox tool becomes a runtime function whose description is the tool's |
| 124 | words plus its network in plain language and whose input is the tool's `args` schema; a bad input never becomes a |
| 125 | job. A run is one OpenVibe.Run function job as the person (`X-OV-Subject` + `X-OV-Project`), artifact |
| 126 | `[email protected]`, the pinned inputs, the declared `net` and limits (never above the caps), `ttl_ms` |
| 127 | 120000, and the person's own machines before OpenVibe's pool. No node: a plain message and Link's "Run it on my |
| 128 | machine" link, and nothing runs anywhere else. The tool's JSON comes back as untrusted data, cut to 64 KiB, with the |
| 129 | job id, wall time and exit; Run's per-second metering is the cost. |
| 130 | - **The card and install page** say "Runs code in a sandbox on your machine or OpenVibe's", list each tool with its |
| 131 | network in plain words ("no internet", "OpenVibe sites only", "the internet") and its limits, and show the scan's |
| 132 | findings per tool. A flagged code skill installs only after the person reads them; a failed one never. |
| 133 | - Migration 0047 (`actor_skill_listings.code`, the document's own text, the `skill.run` kind). Tests: |
| 134 | `test/skill-sandbox.test.js`. |
| 135 | |
| 136 | ## Unreleased — an agent's live canvas (HO9) |
| 137 | |
| 138 | - **An agent's live panel beside the conversation** (plan track HO, wave 2; ADR-059, `actor.canvas@1`): the agent calls |
| 139 | `canvas_set({ title, blocks })` and the panel is drawn beside its thread — a trip board, a price table, a checklist, a |
| 140 | small chart — from data only (no HTML, no style, no script). The whole document is replaced and its version grows; |
| 141 | it is validated against the released contract, and a picture outside openvibe.media, a markup block or another |
| 142 | block the contract does not know is refused with the schema's plain reason and nothing is written. One run may call |
| 143 | it at most 20 times. The panel lives in `actor_canvases`: one row per conversation (the thread's first turn), with |
| 144 | the document, its version and the ticks waiting for the next turn (migration 0045). |
| 145 | - **The person's moves, never the canvas's**: a button's label is posted by the API as the person's own message — a |
| 146 | normal turn from the newest turn of the conversation, at the agent's level and through its approvals, exactly as |
| 147 | typing it would (nothing else happens). A checklist tick flips that item in the document (version + 1) and starts |
| 148 | no turn; the next turn is told which item the person ticked, once, as its conversation context. Both go through the |
| 149 | same-origin API (`GET /api/v1/me/canvases?thread=`, `GET /api/v1/me/canvases/:id`, |
| 150 | `POST /api/v1/me/canvases/:id/events`) and another person's canvas is the same 404 as one that does not exist. |
| 151 | - **Where it shows**: the thread page draws it in the third column on a wide screen and as one closed "Canvas · N |
| 152 | items" bar above the composer on a phone (open on tap; the open body scrolls inside at 45vh), with openvibe-shared |
| 153 | v4.145.0's ov-canvas.js. The page redraws it from the thread's live events when `canvas_set` runs; a closed bar |
| 154 | still updates its count and says "updated" for a few seconds. The document is in the account export and goes with |
| 155 | the account. Test: `test/canvas.test.js`; openvibe-contracts v0.341.0 names the routes. |
| 156 | - **Chat can draw it beside a Vibe chat** (HO9 step 2): the two reads answer a cross-origin request from |
| 157 | `https://openvibe.chat` only, with the person's own Network Bearer and no credentials mode (a cookie from another |
| 158 | site is refused), and carry `Vary: Origin`; every canvas write stays same-origin. Test: `test/canvas.test.js`. |
| 159 | |
| 160 | ## Unreleased — the skills registry (plan HO2) |
| 161 | |
| 162 | - **A skill is a document, and the registry vouches for it** (plan HO2, ADR-058; contracts 0.340.0): `actor.skill@1` |
| 163 | is a slug, a name, a one-line description, a version, Markdown instructions, up to ten text resources and what it may |
| 164 | ask an agent to do. It runs as a prompt and nothing else — no code, no binary, no install recipe — and it grants |
| 165 | nothing: the agent's level and its approvals still decide every step. The document's integrity hash is not a |
| 166 | signature (as for an agent's voice): the author in a document is a claim, and the listing is the only place a |
| 167 | publisher is vouched for. |
| 168 | - **The scan comes first** (`server/skills/scan.js`): deterministic, no model, five rules over the words of the |
| 169 | document — an act of a kind the skill did not declare, a request for a password, a key, a token or a seed phrase, |
| 170 | files or notes sent to an address or a URL, a resource that reads as a script, a URL outside the hosts it declared. |
| 171 | A block fails the skill (it never installs), a warning flags it (the person reads the findings and confirms), no |
| 172 | finding passes it (it installs in one tap). |
| 173 | - **OpenVibe's own skills first** (`skills/`): four real documents — a stream recording's summary with its moments, |
| 174 | the last seven days as a changelog draft, a price watch as a goal, a research brief with its sources — published as |
| 175 | listings of publisher kind `openvibe`. Nobody may upload a skill in this wave. |
| 176 | - **Progressive disclosure**: an agent's prompt carries each installed skill's name and description only; the tool |
| 177 | `load_skill(slug)` brings the instructions and the resources, framed as guidance from that skill. A skill changes no |
| 178 | level and no approval. |
| 179 | - **The pages**: `/skills` (the catalogue, the scan's state in words) and `/skills/<slug>` (the instructions, what it |
| 180 | may ask for in plain words, the findings, and the install). The agent's page lists its own skills, with Remove. |
| 181 | `GET /api/v1/skills` and `GET /api/v1/skills/:id` answer the listing; `POST/DELETE /api/v1/me/agents/:id/skills` |
| 182 | install and remove. |
| 183 | - **The curator ships with the catalogue**: a listing nobody has loaded for 30 days goes stale, for 90 days it is |
| 184 | archived, and a stale or archived listing is not offered. The job asks at night what is due; it is off in a drill. |
| 185 | - Migration 0043 (`actor_skill_listings`, `actor_skill_installs`). Both tables go with the person: an account export |
| 186 | carries the installs, and an account deletion erases them. Test: `test/skills.test.js`. |
| 187 | |
| 188 | ## Unreleased — memory that tidies itself (HO5) |
| 189 | |
| 190 | - **An agent's memory that consolidates itself** (plan track HO, wave 2): once a person turns on "Tidy my agents' memory |
| 191 | each night" on /memory, one due-based job runs each due agent's own notes through ONE model call a night, in the |
| 192 | cheapest class that can wait (OpenVibe.AI's `batch`, or `background` when the client cannot ask for batch), and the |
| 193 | answer is DATA: a list of merges, retires and promotions and a short diary, checked against the agent's own notes |
| 194 | before anything happens. The sources of a merge are kept and marked `merged_into`, a stale note is marked |
| 195 | `retired_at` and never deleted, a note that keeps coming up becomes a pinned note and the agent reads pinned notes |
| 196 | first, and the diary is two to five plain sentences in the agent's voice (migration 0041). |
| 197 | - **The rules the model cannot break**: only the agent's own notes are touched — a note the person wrote, or pinned by |
| 198 | hand, is left alone; every id in the answer must be one of the notes that were sent, so an id from another agent or |
| 199 | another person is ignored; a merge longer than its sources together is refused; at most 20 changes a night, per |
| 200 | person; and the person's own words still make the only active memory. |
| 201 | - **The person sees it and corrects it**: /memory and the agent's page show the latest diary entry and every change, |
| 202 | each with Undo for thirty days (an undo brings the sources back and drops the merged note). A diary entry can be |
| 203 | edited or deleted, and a note can be pinned by hand. |
| 204 | - **Consent and the job**: the setting is off by default and lives in a row per person with a `next_due_at` (never a |
| 205 | weekly interval in the code); nothing runs for a person who has not turned it on, and the job is off in a drill and in |
| 206 | a test. The diary and the history of the nights are in the account export and go with the account (ADR-033). |
| 207 | Test: `test/memory-tidy.test.js`. |
| 208 | ## Unreleased — triggers in conversation |
| 209 | |
| 210 | - **The routine's card in the chat** (Opus): the turn that made a trigger shows it — when, in words (with its zone), |
| 211 | what runs, the next run in the reader's own time, how the last run went (a link to it), which agent runs it, and On, |
| 212 | Paused or Deleted. Its moves are plain forms that work with no script: Pause or Resume, Run now, and Undo for ten |
| 213 | minutes, then Delete with a confirmation; a routine paused after failed runs says so and leads with Resume. Only the |
| 214 | turn's requester, same-origin, and only a trigger that turn made (`POST /chat/:id/trigger/:tid`); Watch is called with |
| 215 | the person's session. Schedules read the way a person says them: "Every hour at :30" (was "Every 30 minutes"), |
| 216 | "Every 15 minutes", "Every 6 hours", "Every day at 08:00 and 20:00", "Every month on the 1st at 09:00", "Every year |
| 217 | on 25 December at 09:00"; a rule with no plain phrase is "On a custom schedule, <cron>". Test: `test/trigger-card.test.js`. |
| 218 | - **Triggers made in the conversation** (plan §12 A-4): `schedule_trigger` turns "every weekday at 9, summarise my inbox" |
| 219 | or "when a new issue lands in my repo, triage it" into a Watch subscription the person owns, created with their own |
| 220 | token — never Actor's service token acting for them. The tool parses the sentence, and when it cannot (no time, no |
| 221 | timezone, two times, no event it can name) it makes nothing and asks the one question instead. The card is a |
| 222 | `trigger` step on the turn: when in words and cron, what it runs, the next run, the last result (ok, failed, needs |
| 223 | you) and active/paused (migration 0037). |
| 224 | - **The person's moves** are Actor routes: `GET/POST /api/v1/triggers`, `PATCH /api/v1/triggers/:id`, `…/pause`, |
| 225 | `…/resume`, `…/run` and `DELETE` (undo for ten minutes, then Delete with a confirmation). Another person gets 404. |
| 226 | At most 20 active triggers, the smallest interval is 15 minutes, and five failed runs in a row pause the trigger and |
| 227 | say so on the card. |
| 228 | - **Watch runs come back as assignment roots** with origin `routine` and the trigger's own level, capped there: a |
| 229 | routine cannot borrow a higher standing level from its agent. Money, passwords, deletions and new recipients still |
| 230 | always ask inside the run. |
| 231 | - Watch gets the routine's cron (`POST /api/v1/watches/:id/schedule`), a scheduled check that queues the action without |
| 232 | fetching, and its own five-failed-check pause; an actor-agent delivery now names the watch and the Actor trigger. |
| 233 | - Contracts 0.330.0 adds `actor.trigger@1` and the `trigger` step on `actor.task-event@2`; Actor still pins 0.328.0 |
| 234 | until it is released, so the routes are guarded by `actor.task.read`/`actor.task.create` in the meantime. |
| 235 | |
| 236 | ## Unreleased — one Computer |
| 237 | |
| 238 | - **One Computer** (plan 2026-11-07: "Surf, Computer and Actor are one experience"): when a task opens a desk, its |
| 239 | own step carries `computer` (`session_id` — OpenVibe.Run's `ses_…`, or null on the person's own machine through |
| 240 | Bot — `machine`, `where` and `cost_hint`) from the tool's answer, never the model's words. `GET /api/v1/tasks/:id` |
| 241 | reads the same object off the task's own steps, with `driving` while the person holds the desk, and |
| 242 | `agent.timeline-entry@1` stores it (migration 0035). |
| 243 | - **Take over / Give it back** are one API on the task: `POST /api/v1/tasks/:id/takeover` and `…/giveback`, built on |
| 244 | the `hand_to_person` hand-off. While the person drives, `computer_input` and the acting `computer_browser` actions |
| 245 | are refused with a clear reason; the task's timeline gets one `handoff` step and the Dock's timeline one step with |
| 246 | the same Computer. Only the task's own person. |
| 247 | - **The still**: `GET /api/v1/tasks/:id/still` asks the session's own service (Run) for the newest frame as Actor's |
| 248 | service token acting for the person, and answers the bytes with `Cache-Control: private, no-store`. A person's |
| 249 | task only; another person, a signed-out visitor and an app token all get the same 404 as a missing task. |
| 250 | |
| 251 | ## 0.3.0 — 2026-11-07 |
| 252 | |
| 253 | - **Space's builder as a task of the person's one agent** (plan 2026-10-22 §Z, stage Z1): six new tools — `space_create`, `space_files_list`, `space_files_read`, `space_files_write`, `space_preview` and `space_publish`. The agent works on the person's own spaces through OpenVibe.Space's builder API (`/api/v1/builder/spaces`), as the person: another person's space is the same 404 as one that does not exist, and every write goes through the same path, limits and audit as Space's own editor. |
| 254 | - **Publishing waits for the person:** `space_publish` asks, and the answer lives in the Dock ("Needs you"); the tool says the space is not published yet until the person says yes. |
| 255 | |
| 256 | ## 0.2.0 — 2026-11-07 |
| 257 | |
| 258 | - **The one timeline behind the Dock** (design 2026-11-07): every mode of the agent (Chat, Codes, Run, Watch, Live, Surf) publishes the step it took as agent.step.started|updated|ended, and Actor keeps the one timeline: GET /api/v1/agent/timeline (cursor, mode and needs-you filters, the per-mode counts) and the live stream GET /api/v1/agent/timeline/stream. An entry is a title, an outcome and a link: the table has no column for a prompt or a diff, so none can be stored. |
| 259 | - **Needs you and the kill switch:** POST /api/v1/agent/approvals/:product/:id/decide answers an approval in the mode that owns it (the person's own token goes with it), and POST /api/v1/agent/kill-switch stops what is open and pauses the agent until the person resumes it. |
| 260 | - **Only me by default:** an entry is private until the person shares it through the one Share sheet; another person's entry is the same 404 as one that does not exist. The timeline is in the account export and goes with the person on deletion. |
| 261 | |
| 262 | ## 0.1.0 — 2026-10-08 |
| 263 | |
| 264 | - **First release:** the task router (plan T17, ADR-044). A task is classified, routed by `openvibe-sdk/placement`, run, checked by a second model family, and delivered as `platform.task@1` with its cost and explanation. |
| 265 | - **Agents:** the OpenVibe runtime (DeepSeek acting through OpenVibe.Search and OpenVibe.Tools), OpenAI's web agent, and an open model on OpenVibe's server for private mode. OpenVibe.Codes is listed for coding. |
| 266 | - **API:** tasks, a live stream, cancel, the agent catalog and a dry-run router. Capabilities: `actor.task.create`, `actor.task.read`, `actor.task.list`, `actor.agent.read` (openvibe-contracts 0.115.0). |
| 267 | - **Money:** a free tier per person and an operator daily ceiling. Budgets are hard. |
| 268 |