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.

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