Kotoba

Where to start

What Kotoba isWho she is and where she runs, in one page
InstallingOne package, two commands
First runA key, a model, her first words
The approval gateHow she asks before she acts
The two voice modesLocal voice, or the agent tunnel
The soul fileChange who she is
RoadmapWhat grows next, and what was cut on purpose

Or a section

↑↓ move openesc close124 pages
All pages

The agent4 of 15

Core tools

About 6 minutes to read

On this page

Seven tools in the core toolset. They are the ones that talk to you rather than to a machine: starting and stopping a job, asking a question, putting a card on your screen, keeping a plan.

All seven declare risk: read — including start_work, because launching a job is harmless in itself; the work is gated inside the job's own loop.


start_work — hand a heavy task to the background

Companion mode only. Returns immediately.

Takes: goal — one sentence, written in the language you are speaking. The schema is explicit about why: "the worker produces its files and its summary in the language it is briefed in, so an English goal for a Spanish request gives them an English report."

Refuses: a second job while one is already running. It returns the current goal and tells her to ask you to wait.

What you see: a work_started frame, then the job's own rows.

What the model is told back is deliberately thin:

"The job has been LAUNCHED in the background — that is all that has happened so far: nothing has been opened, read, built or run yet. Say in ONE short line that you're on it and they can watch the screen, in the future tense, and claim nothing you haven't done."

Details: The two modes.


cancel_work — stop it

Companion mode only. Takes no arguments.

Cancels the runner task, clears the work state, and cancels any deferred approval still waiting — an approved-but-detached command runs outside the work state and used to survive a "stop".

Logs on every call, because the terminal's /stop calls execute() directly and no toolcall line would otherwise cover it.

Says "there's nothing running in the background right now" when there is nothing to stop.


ask_user — open a box for you to type into

Takes: prompt (the box's label, under 60 characters — the schema is blunt that this is not a message and not an explanation), optional detail shown only if you expand it, kind in text | link | key, and name when kind="key".

Two completely different behaviours, decided by the turn:

WhereBehaviour
A spoken conversation (channel="voice")Non-blocking. The card opens, the turn ends, and your typed entry arrives as your next message. A long wait inside an ElevenLabs turn kills the WebSocket.
Work mode, or any channel="text" turnBlocks for up to 300 seconds and hands the value straight back to the model.

channel here is the clock, not the register. In the default voice_mode: local, a message you type into the web app is channel="text" and blocks; a spoken one is channel="voice" and does not. The terminal always passes channel="text" and answers the card in place. In voice_mode: agent even a typed message arrives relayed by ElevenLabs, so it keeps the voice clock.

Refuses:

  • kind="secret" — always. Use ask_secret.
  • kind="key" or "secret" in the blocking branch — that branch echoes the value into the model's context, which a secret must never enter.
  • kind="key" with no name — the value would have nowhere to be stored and would be silently dropped.
  • Anything, when no screen is listening. The card is not opened, and the model is told plainly: "There is no screen to put that box on, so NOTHING was opened and nobody can type into it. Do NOT tell the user a box is waiting."

That last refusal is the pattern this whole file repeats. Frames are dropped silently when nothing is listening, and for a while the guidance still said "I opened a secure field on screen" regardless — so she told a user to type an API key into a field that did not exist, then waited for a message nobody could send.

A key is stored backend-only and never re-enters the conversation.


clarify — ask one question

Takes: question.

In a conversation the question is the output: it comes straight back as the tool result, she reads it aloud, and your reply is the next turn.

In work mode there is no next turn. The job runs against a queue nobody reads, so the same echo asked into the void — one run ended 4.7 seconds in carrying "Which page should I open?" as its summary, announced as a finished result. So in work mode it blocks on a real card (180 s), and a question that cannot be drawn anywhere is refused before it is asked rather than lost after.

Its four possible endings are told apart: answered, declined, expired, or never drawn.


Takes: url (must start with http:// or https://), and why — one line.

It never opens anything. It shows a card and you accept or decline. Returns immediately; it does not block the turn.

Refuses a file:, javascript: or scheme-less URL, and says so as a refusal rather than a failure so the model can retry with a real address.

When no screen is listening it says so and tells her to name the site in words or offer to save the link to your files instead. A voice turn also cannot read a URL aloud — the spoken filter cuts it — so with no screen there is genuinely nothing to hand you.


todo — her own task list

Not a deliverable and not something you ask for. She decides when a job is involved enough to be worth tracking, and the list renders on screen.

Takes: steps to create or replace (max 20, each a string or {text, detail}), or done / active / drop / close to update the open list. Send those alone.

Refuses:

  • Re-sending the same steps as a plan that is already open — that is read as an update, not a replacement, and the result names the field it dropped.
  • Re-sending steps to a list that is closed — "That plan is already finished and closed — don't reopen it."
  • Any change to a plan owned by another run. A background job's plan is the job's to tick and close; the companion turn that launched it shares the session and is refused.
  • Opening a new plan on the turn that announces a finished job.

Indices are 1-based. Ones that name no step, or a step already settled, come back in an Ignored: note rather than vanishing into a success line. Closing with steps still unmarked marks the list abandoned, not done.

Per-turn cap: 10 calls (shared with cronjob), against the default 3 for everything else.


view_capture — look at a screenshot again

Takes: file — the filename of a capture listed in her RECENT CAPTURES block.

Screenshots she takes persist in your Files under screenshots/<source>/. The work turn that took them is long gone by the time you ask a follow-up, and old images are elided from context mid-turn. This reads one back off disk and returns it as an image, so the vision model actually sees it again.

Resolution is jailed to the file library and tries three things in order: the path as given, the basename in the root, then a recursive search for the basename (newest match wins). A symlink or .. escape is rejected.

Read-only and companion-safe, so a normal voice follow-up can use it.

For entities rather than filenames — "his profile photo" — use recall_image instead. See Memory.