openvibers/openvibe.actor CHANGELOG.md
CHANGELOG.md
Changelog
Unreleased — agents have souls
- A soul (
agents.soul@1, Contracts 0.424.0;openvibe-sdk/agents/soul0.165.0; migration 0072): who a personal
agent is, kept apart from its instructions and its memory.actor_agents.soulis jsonb (null: no soul yet); a create
and a patch take asoulthat the SDK validates, and a catalogue answer carries it back with itssoul_md. - The prompt: a soul is the first block of a personal agent's prompt (
toPrompt(soul, { name })) and the first
prompt layer, before the person's instructions, so the cached prefix stays stable. It says who the agent is, never
what it may do. - Import:
POST /api/v1/agents/:id/soul/importtakes aSOUL.mdof at most 20 KB and stores what
fromSoulMdreads; an invalid result (a secret, a bad part) is 422. - Suggestions (Design rule 176):
POST /api/v1/agents/:id/soul/suggestwaits inactor_agent_proposalsas kind
soulwithchange()'s words; the person accepts or dismisses it on the existing suggestions route. An agent never
writes its own soul. - Your agents in the menu:
GET /api/v1/me/agents/facesanswers each face's name, avatar, hue, glyph, state
(working, asks, paused, resting), current step and number of asks, newest activity first and at most twelve; the
same first-party CORS as the Actor strip, cached privately for 15 seconds. - Pins: openvibe-contracts v0.424.0, openvibe-sdk v0.165.0.
Unreleased — every AI call measured
- AI meter (
openvibe-sdk/ai-meter, SDK 0.164.0): every model call Actor makes straight to a provider is recorded
and sent to OpenVibe.AI'sPOST /api/v1/usage/calls(a call through OpenVibe.AI, with a person's own key or the
router, is recorded by AI itself, so it is never counted twice): provider,
model, task and call id, TTFT, tokens per second, latency, tokens, tool calls, the outcome, a failure's class, and
the task's wall time on its last step. Actor's service token is narrowed toai.usage.report. The meter is off in
a drill and in tests, and it never fails or blocks a model call. - Pins: openvibe-contracts v0.421.0, openvibe-sdk v0.164.0.
Unreleased — make your own agent (blueprints)
- Blueprints (
agents.blueprint@1, Contracts 0.419.0): a person's agent as one document of ten parts. POST /api/v1/blueprintsmakes a draft, checked against the schema andopenvibe-sdk/agents/blueprint's rules;
a blueprint carries no secret.PUT …/:id/draftedits it, andPOST …/:id/publishfreezes it as version N. A published version never
changes.GET /api/v1/blueprintslists mine (?scope=publiclists the gallery), andGET …/:id?version=Nreads one
version.POST …/:id/remixmakes a private copy that credits its source, only when the author named a licence.- Installs (
agents.install@1): GET …/:id/asksis the install screen in words.POST …/:id/installmakes the person's own agent once every ask is agreed and the inputs are filled. Its
instructions carry the inputs and the floor in words.- When a version is published, an install set to
same-or-lesstakes it if it asks for no more. Any other install
keeps itpending. POST /api/v1/agents/:id/install/updatetakes the new version once its new asks are agreed.- Migration 0071 adds the blueprint, version and install tables and lets an agent's instructions run to 20,000
characters. - Pins: openvibe-contracts v0.419.1, openvibe-sdk v0.162.0.
Unreleased — Stop, not E-STOP
- The robot tools and page copy say Stop;
list_my_robotsno longer reads a latch field.
What changed in OpenVibe.Actor, newest first. Each site also publishes its patch notes at /updates.
Unreleased — the same run shape as Codes and Run (agents.run@1, agents.step@1)
GET /api/v1/runslists the person's own runs newest first (limit,before,status,agent) in the one
agent system'sagents.run@1shape: owner, agent and product, parent run, budget, status, timestamps, result
summary and cost. A task is the run; nothing new is stored.GET /api/v1/runs/:id/steps?after=reads the task's own event log asagents.step@1, one entry per output
event, with the task event's seq as the cursor.GET /api/v1/runs/:idanswers the same run shape when the reader
asks for it withAccept: application/vnd.openvibe.agents.run+json(whatopenvibe-sdk/agentssends) or
?shape=agents.run@1; the existingagent.run@1snapshot stays the default for its callers.- Read-only and behind the existing
actor.task.read/actor.task.list: only the person's own Network token or
session, and another person's run is the same 404 as one that does not exist. Actor's tables are unchanged. - The field map and what does not fit (per-step cost, Actor's
needs_you, a tool call and its result as two log
entries) are in OpenVibe.Contractsdocs/agents-runs.md; the routes are in [docs/agent-runs.md](docs/agent-runs.md).
Tests:test/runs-api.test.js.
Unreleased — See it work (W1): the desk, the viewer and the replay
- The desk tile in a running task's card: the desk's private Live stream (started with the task's desk through Link's
desk.streamand stopped with the task), with the still at 1/s when no stream is up. Under it the latest step in
plain words, a ring where it last clicked, the browser page's address and where it is ("Your PC · its own desk",
"OpenVibe computer"). The tile pauses its stream while off screen. - The viewer (a tap on the tile): the desk fills a phone and sits beside the steps from 900 px, with Take over,
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
desk (their token, mapped to desk coordinates); the agent's input is refused while they drive. Hand back takes an
optional note that reaches the run as the person's message. Ahand_to_personstep is an Ask that opens the viewer
in control. - Replay: every computer step keeps its still and its action. A finished task's card has a timeline to scrub, and
each step opens the picture it saw. Typed text is redacted before it reaches the task's events, so neither the replay
nor the task log carries it; a click keeps only its x,y. - Migration 0070 (task stills);
GET /api/v1/tasks/:id/desks,/desk-still,/replay, the desk take-over/hand-back
and the person's input. Tests:test/see-it-work.test.js; screenshots:test/see-it-work-shots.js.
Unreleased — the chat is the one place you use Actor (one agent system, stage 1)
- Composer v2 (openvibe-shared 4.215.0, the
agentpreset): the chat mountsOpenVibeComposer.mountwith Attach,
Speak, the mode chip (Fast, Balanced, Best, Cheapest, Private) and the round send; files go through Actor's existing
path (POST /chatwith the file as data) and their chips show the read's progress. The dashed "Attach files" box and
the separate model/mode controls are gone; the model lives at/chat/model. - Settings (
/chat/settings): the run defaults ("New runs: Only me … Apply to all my existing runs") moved off the
chat. The route (POST /chat/defaults) and its behaviour are unchanged. - Four suggestion chips on an empty chat, one line each, instead of the wall of starter cards; a chat with messages
shows none. - The Console is folded in:
/consoleanswers 301 to/chat(carrying?ask=/?from=), the bottom tab bar is
Home, Chat, Agents, and the running tasks the Console listed are the chat's "Now" strip — one line each, Stop on each,
hidden when nothing runs./me/spendand the approvals, agents, computers and robots APIs and pages stay. - A running task is a card in the conversation (title, state, the last steps, Stop), refreshed in place from
GET /chat/turn/:id; stopping goes throughPOST /chat/:id/canceland returns to the chat. - Migration-free. Tests:
test/one-page.test.js, plus the updated chat, console, model, sharing, allowance and
self-host suites; screenshots at 390 and 1280:test/one-page-shots.js.
Unreleased — skills that run code, sandboxed (HO8 step 3)
actor.skill@2: code in a sandbox (plan HO8, ADR-060; contracts 0.343.0): a sandbox skill carries one to five
tools and its code as ordinary.jstext resources. The registry reads the code, never runs it, and fails a tool
that readsprocess.env, starts a process, worker orvm, writes a file, builds code at run time, requires anything
but Link's safe modules, carries an encoded blob or minified code, or reaches the network outside thenetits tool
declares; it flags any network use, timers over 5 s and loops over input. Every finding names its tool. The
cross-field rules (a tool's entry is a resource, every code resource is a tool's entry, tool names are unique) are
checked before anything is listed.- The bytes that run are the bytes that were scanned: publishing a sandbox skill stores each code resource as a
private OpenVibe.Media object under Actor's tenant and pins{ name, media_id, sha256 }on the
actor.skill-listing@2;server/skills/publishis the registry's path (a prompt skill staysactor.skill@1). skill.run: a new HO1 kind ("running a skill's code in a sandbox"), allowable, with the exact target
<slug>@<version> <tool>(plus· internetwhennetispublic), so "always allow" covers one version's tool.- The tool the agent calls: each installed sandbox tool becomes a runtime function whose description is the tool's
words plus its network in plain language and whose input is the tool'sargsschema; a bad input never becomes a
job. A run is one OpenVibe.Run function job as the person (X-OV-Subject+X-OV-Project), artifact
[email protected], the pinned inputs, the declarednetand limits (never above the caps),ttl_ms
120000, and the person's own machines before OpenVibe's pool. No node: a plain message and Link's "Run it on my
machine" link, and nothing runs anywhere else. The tool's JSON comes back as untrusted data, cut to 64 KiB, with the
job id, wall time and exit; Run's per-second metering is the cost. - The card and install page say "Runs code in a sandbox on your machine or OpenVibe's", list each tool with its
network in plain words ("no internet", "OpenVibe sites only", "the internet") and its limits, and show the scan's
findings per tool. A flagged code skill installs only after the person reads them; a failed one never. - Migration 0047 (
actor_skill_listings.code, the document's own text, theskill.runkind). Tests:
test/skill-sandbox.test.js.
Unreleased — an agent's live canvas (HO9)
- An agent's live panel beside the conversation (plan track HO, wave 2; ADR-059,
actor.canvas@1): the agent calls
canvas_set({ title, blocks })and the panel is drawn beside its thread — a trip board, a price table, a checklist, a
small chart — from data only (no HTML, no style, no script). The whole document is replaced and its version grows;
it is validated against the released contract, and a picture outside openvibe.media, a markup block or another
block the contract does not know is refused with the schema's plain reason and nothing is written. One run may call
it at most 20 times. The panel lives inactor_canvases: one row per conversation (the thread's first turn), with
the document, its version and the ticks waiting for the next turn (migration 0045). - The person's moves, never the canvas's: a button's label is posted by the API as the person's own message — a
normal turn from the newest turn of the conversation, at the agent's level and through its approvals, exactly as
typing it would (nothing else happens). A checklist tick flips that item in the document (version + 1) and starts
no turn; the next turn is told which item the person ticked, once, as its conversation context. Both go through the
same-origin API (GET /api/v1/me/canvases?thread=,GET /api/v1/me/canvases/:id,
POST /api/v1/me/canvases/:id/events) and another person's canvas is the same 404 as one that does not exist. - Where it shows: the thread page draws it in the third column on a wide screen and as one closed "Canvas · N
items" bar above the composer on a phone (open on tap; the open body scrolls inside at 45vh), with openvibe-shared
v4.145.0's ov-canvas.js. The page redraws it from the thread's live events whencanvas_setruns; a closed bar
still updates its count and says "updated" for a few seconds. The document is in the account export and goes with
the account. Test:test/canvas.test.js; openvibe-contracts v0.341.0 names the routes. - Chat can draw it beside a Vibe chat (HO9 step 2): the two reads answer a cross-origin request from
https://openvibe.chatonly, with the person's own Network Bearer and no credentials mode (a cookie from another
site is refused), and carryVary: Origin; every canvas write stays same-origin. Test:test/canvas.test.js.
Unreleased — the skills registry (plan HO2)
- A skill is a document, and the registry vouches for it (plan HO2, ADR-058; contracts 0.340.0):
actor.skill@1
is a slug, a name, a one-line description, a version, Markdown instructions, up to ten text resources and what it may
ask an agent to do. It runs as a prompt and nothing else — no code, no binary, no install recipe — and it grants
nothing: the agent's level and its approvals still decide every step. The document's integrity hash is not a
signature (as for an agent's voice): the author in a document is a claim, and the listing is the only place a
publisher is vouched for. - The scan comes first (
server/skills/scan.js): deterministic, no model, five rules over the words of the
document — an act of a kind the skill did not declare, a request for a password, a key, a token or a seed phrase,
files or notes sent to an address or a URL, a resource that reads as a script, a URL outside the hosts it declared.
A block fails the skill (it never installs), a warning flags it (the person reads the findings and confirms), no
finding passes it (it installs in one tap). - OpenVibe's own skills first (
skills/): four real documents — a stream recording's summary with its moments,
the last seven days as a changelog draft, a price watch as a goal, a research brief with its sources — published as
listings of publisher kindopenvibe. Nobody may upload a skill in this wave. - Progressive disclosure: an agent's prompt carries each installed skill's name and description only; the tool
load_skill(slug)brings the instructions and the resources, framed as guidance from that skill. A skill changes no
level and no approval. - The pages:
/skills(the catalogue, the scan's state in words) and/skills/<slug>(the instructions, what it
may ask for in plain words, the findings, and the install). The agent's page lists its own skills, with Remove.
GET /api/v1/skillsandGET /api/v1/skills/:idanswer the listing;POST/DELETE /api/v1/me/agents/:id/skills
install and remove. - The curator ships with the catalogue: a listing nobody has loaded for 30 days goes stale, for 90 days it is
archived, and a stale or archived listing is not offered. The job asks at night what is due; it is off in a drill. - Migration 0043 (
actor_skill_listings,actor_skill_installs). Both tables go with the person: an account export
carries the installs, and an account deletion erases them. Test:test/skills.test.js.
Unreleased — memory that tidies itself (HO5)
- An agent's memory that consolidates itself (plan track HO, wave 2): once a person turns on "Tidy my agents' memory
each night" on /memory, one due-based job runs each due agent's own notes through ONE model call a night, in the
cheapest class that can wait (OpenVibe.AI'sbatch, orbackgroundwhen the client cannot ask for batch), and the
answer is DATA: a list of merges, retires and promotions and a short diary, checked against the agent's own notes
before anything happens. The sources of a merge are kept and markedmerged_into, a stale note is marked
retired_atand never deleted, a note that keeps coming up becomes a pinned note and the agent reads pinned notes
first, and the diary is two to five plain sentences in the agent's voice (migration 0041). - The rules the model cannot break: only the agent's own notes are touched — a note the person wrote, or pinned by
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
another person is ignored; a merge longer than its sources together is refused; at most 20 changes a night, per
person; and the person's own words still make the only active memory. - The person sees it and corrects it: /memory and the agent's page show the latest diary entry and every change,
each with Undo for thirty days (an undo brings the sources back and drops the merged note). A diary entry can be
edited or deleted, and a note can be pinned by hand. - Consent and the job: the setting is off by default and lives in a row per person with a
next_due_at(never a
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
a test. The diary and the history of the nights are in the account export and go with the account (ADR-033).
Test:test/memory-tidy.test.js.
Unreleased — triggers in conversation
- The routine's card in the chat (Opus): the turn that made a trigger shows it — when, in words (with its zone),
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,
Paused or Deleted. Its moves are plain forms that work with no script: Pause or Resume, Run now, and Undo for ten
minutes, then Delete with a confirmation; a routine paused after failed runs says so and leads with Resume. Only the
turn's requester, same-origin, and only a trigger that turn made (POST /chat/:id/trigger/:tid); Watch is called with
the person's session. Schedules read the way a person says them: "Every hour at :30" (was "Every 30 minutes"),
"Every 15 minutes", "Every 6 hours", "Every day at 08:00 and 20:00", "Every month on the 1st at 09:00", "Every year
on 25 December at 09:00"; a rule with no plain phrase is "On a custom schedule, <cron>". Test:test/trigger-card.test.js. - Triggers made in the conversation (plan §12 A-4):
schedule_triggerturns "every weekday at 9, summarise my inbox"
or "when a new issue lands in my repo, triage it" into a Watch subscription the person owns, created with their own
token — never Actor's service token acting for them. The tool parses the sentence, and when it cannot (no time, no
timezone, two times, no event it can name) it makes nothing and asks the one question instead. The card is a
triggerstep on the turn: when in words and cron, what it runs, the next run, the last result (ok, failed, needs
you) and active/paused (migration 0037). - The person's moves are Actor routes:
GET/POST /api/v1/triggers,PATCH /api/v1/triggers/:id,…/pause,
…/resume,…/runandDELETE(undo for ten minutes, then Delete with a confirmation). Another person gets 404.
At most 20 active triggers, the smallest interval is 15 minutes, and five failed runs in a row pause the trigger and
say so on the card. - Watch runs come back as assignment roots with origin
routineand the trigger's own level, capped there: a
routine cannot borrow a higher standing level from its agent. Money, passwords, deletions and new recipients still
always ask inside the run. - Watch gets the routine's cron (
POST /api/v1/watches/:id/schedule), a scheduled check that queues the action without
fetching, and its own five-failed-check pause; an actor-agent delivery now names the watch and the Actor trigger. - Contracts 0.330.0 adds
actor.trigger@1and thetriggerstep onactor.task-event@2; Actor still pins 0.328.0
until it is released, so the routes are guarded byactor.task.read/actor.task.createin the meantime.
Unreleased — one Computer
- One Computer (plan 2026-11-07: "Surf, Computer and Actor are one experience"): when a task opens a desk, its
own step carriescomputer(session_id— OpenVibe.Run'sses_…, or null on the person's own machine through
Bot —machine,whereandcost_hint) from the tool's answer, never the model's words.GET /api/v1/tasks/:id
reads the same object off the task's own steps, withdrivingwhile the person holds the desk, and
agent.timeline-entry@1stores it (migration 0035). - Take over / Give it back are one API on the task:
POST /api/v1/tasks/:id/takeoverand…/giveback, built on
thehand_to_personhand-off. While the person drives,computer_inputand the actingcomputer_browseractions
are refused with a clear reason; the task's timeline gets onehandoffstep and the Dock's timeline one step with
the same Computer. Only the task's own person. - The still:
GET /api/v1/tasks/:id/stillasks the session's own service (Run) for the newest frame as Actor's
service token acting for the person, and answers the bytes withCache-Control: private, no-store. A person's
task only; another person, a signed-out visitor and an app token all get the same 404 as a missing task.
0.3.0 — 2026-11-07
- 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_previewandspace_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. - Publishing waits for the person:
space_publishasks, and the answer lives in the Dock ("Needs you"); the tool says the space is not published yet until the person says yes.
0.2.0 — 2026-11-07
- 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.
- 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.
- 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.
0.1.0 — 2026-10-08
- 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 asplatform.task@1with its cost and explanation. - 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.
- 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). - Money: a free tier per person and an operator daily ceiling. Budgets are hard.