Witbitz docs HomeTrustAll docs

Tools and widgets

In Witbitz, tools are how an agent reaches capability, and widgets are how tool results become shared application state. The important distinction is that a widget is not one user's private chat decoration. It is part of the Space that every member can see.


Tools are declared by the Space

A Space's sealed config names the tools available to the agent:

await client.create({
  agentName: 'Planner',
  persona: 'Plan trips with the group and keep decisions clear.',
  tools: ['search_places', 'show_places', 'show_chart', 'write_pdf']
})

The render opens this config during a turn and exposes the declared tools to the agent. If the config is sealed, the platform cannot read the persona, tool list, admission policy, or model config at rest.

The built-in catalogue

These are the tools a hosted Space can name in its config today. A Space only gets what it declares — an empty tools list is an agent that can talk and nothing else.

Tool What it does Produces
search_places Query Google Places for candidates. Text — the agent then picks
show_places Put chosen places (by id) on the shared map. places widget
add_place Add one place to the existing map doc. same places widget
search_flights Query Duffel for real offers. Text — the agent then picks
show_flights Put chosen offers (by id) on the shared card. flights widget
set_itinerary Replace the whole day-by-day plan. itinerary widget
add_to_itinerary Append to the existing plan. same itinerary widget
show_chart Draw data as SVG. chart widget
show_diagram Draw a relationship graph as SVG. diagram widget (same page)
show_photo Put an image in the reply. Sealed out-of-line blob
read_file Read a shared PDF / Word / Excel / CSV. Text
read_url Fetch a public URL (SSRF-guarded). Text
write_pdf Generate a PDF from Markdown. File on the reply

Query-then-show is deliberate. search_* returns candidates to the agent; a second call puts the chosen ids on the shared doc. The member sees a curated set, not a raw result dump, and the agent's choice is the part that gets sealed into the room.

Two widget kinds are not agent-produced: location (a member shares live location from the composer) and nav (turn-by-turn, opened from a place card). The client can also render trip and shop docs, which no current first-party tool emits.

Any shared view can be opened full-screen from the room's menu — a widget is a living document, so reaching it must not depend on scrolling back to the message that first posted it.

Tool results become room artifacts

Tools can return different kinds of results:

Result Example
Text A searched page summary or calculation result.
Widget A map, chart, diagram, itinerary, route, or flights card.
File A generated PDF attached to the agent reply.
Image/blob A sealed out-of-line photo or generated image.
Proposal A high-stakes action waiting for human approval.

The agent reply can carry pointers to widgets or files created during the same turn. The client renders those pointers as live shared UI.

Shared widget state

The state op stores a named shared widget document. A member or tool can set a patch and summary; later reads return the latest state. The state is sealed with the room key.

await client.state(room, mk, 'trip-plan', {
  days: [
    { name: 'Day 1', items: [{ text: 'Arrive and check in' }] }
  ]
}, 'One-day starter itinerary', 'Ada')

Because the document belongs to the Space, every member sees the same widget state.

High-stakes tools become proposals

An agent should not directly run actions that spend money, change external systems, or cross a policy boundary. Instead, the turn records a proposal. A human later approves or denies it:

const pending = await client.pending(room, mk)

await client.decide(room, mk, pending.proposals[0].id, true, 'Ada')

Only an approved proposal executes, and only once.

Read: Delegated authority

Air-gap behavior

When AIRGAP=1 is enabled in an on-prem deployment, internet-touching tools are refused server-side. Local tools such as chat, document reading, PDF generation, charts, and diagrams continue to work. Map/photo/search/flight tools need either local replacements or must stay disabled.

Read: Enterprise and on-prem

Code map

Concern File
Tool declaration and validation agent/affordance.mjs, agent/agentRecord.mjs
Space tool execution agent/spaceHandler.mjs, agent/spaceService.mjs
Shared widget docs agent/sessionStore.mjs, spaces/public/spaceClient.js
Widget renderers spaces/public/*Widget.*
Delegated actions agent/delegatedAuthority.mjs

See also — the inverse direction: a widget puts your app's UI inside a room; Embed a Space puts a whole room inside your app's page (a cross-origin iframe + an origin-checked bridge, content-blind either way).

Machine-readable source: tools-widgets.md · every doc in one fetch: llms-full.txt (HTML) · ← agent-turns · embed