Enable built-in tools by name, or register your own Python handlers. Both stream into the same UI.
Tools come from two places. Built-in tools ship with the SDK and are enabled by
name. Custom tools are JSON schemas you define with async handlers you write.
llm = ( cycls.LLM() .model("anthropic/claude-sonnet-4-6") .allowed_tools(["Bash", "Editor", "WebSearch", "Canvas"]) # built in .tools(MY_TOOLS) # your schemas .on("create_ticket", create_ticket) # your handler)
Each name enables one or more tools and brings its own prompt guidance, so
enabling it is the only switch you need.
Name
What the model gets
Bash
bash: run shell commands in a sandbox rooted at the workspace
Editor
read and edit: view and modify workspace files
WebSearch
web_search and web_fetch, or the provider’s native search
Browser
browser: drive a real Chrome session, only offered when a browser service is configured
DataBase
database: a per-user key-value store with prefix scans
Canvas
canvas: open a finished file in the side panel viewer
Apps
build_app: bundle a source folder into an installable mini app
Suggest
suggest: one follow-up chip above the composer
Ask
ask: up to three questions on one card, which ends the turn
Bash
Editor
WebSearch
Browser
DataBase
Canvas and Apps
Suggest and Ask
Runs inside a bubblewrap sandbox with the user’s workspace bound at
/workspace and a sanitized environment. The working directory is the
workspace, scratch belongs in .tmp/, and /tmp is per-command and discarded.
Network access is on by default so curl, pip and git work. A prompt
injection can exfiltrate anything the sandbox can read, so turn it off when the
agent does not need it:
read renders files, including PDFs page by page and images for vision models.
edit creates and modifies files. The model is told to use these rather than
cat or sed, which keeps writes inside the safety checks and off the output
token budget.One read returns at most 50,000 characters and ends with the line to continue
from, so a large file or attachment arrives in pages instead of filling the
context window.Paths are workspace relative. Traversal outside the workspace is refused, and so
are the reserved internal directories.
brave is the portable pair, web_search plus web_fetch. It works on every
provider and needs BRAVE_API_KEY. Results arrive in the UI as one sources
row of citation chips at the end of the answer. native uses the provider’s
server-side search, which is Anthropic only today.
A real Chrome session driven step by step: open, read, click, type,
press, back, evaluate, screenshot, download. The page persists between
calls in a turn, so logins and multi-step forms work.The browser itself runs in a shared service, not in your image. Configure it with
environment variables, and the tool is not offered when they are unset:
A per-user JSON key-value store with get, put, delete and scan. It is
private to the user: no teammate and no app can read it. Use it for agent memory
across chats, such as preferences and task progress.Users manage it in the web client under Settings, General, Memory. Each entry in
the active workspace shows as a plain-text note they can edit or delete. Turning
Memory off removes the tool from their chats in every workspace and keeps what
was saved.Anything a teammate or an app needs to read belongs in a workspace file or under
apps/<slug>/data/ instead.
Canvas opens one finished deliverable in the side panel. It renders markdown,
HTML, PDF, images, audio, video, code, CSV, spreadsheets and 3D models. Office
formats render read-only through the office service, and anything else falls back
to a download card.Apps lets the agent bundle a source folder into a single self-contained HTML
file installed in the Apps tab. Apps run under a strict CSP with no external
fetch, and reach their own data through a small bridge, so a dashboard stays live
without holding any key.
Suggest shows one follow-up chip above the composer, written in the user’s
voice. Ask puts up to three questions on one card and ends the turn, with the
answers arriving as the next user message. The options are shortcuts, not a gate:
the user can type anything instead.Users can switch both off in Settings, and context.disabled_tools reflects that
for the turn.
A user can switch a tool off in Settings. LLM.run() drops those tools for the
turn. A switch can never enable a tool the operator did not allow.
A tool schema is a plain dict. A handler is an async function. The return value
goes to the UI stream and to the model as the tool_result, so one return covers
both destinations.
A handler takes the tool input, and optionally a second argument with request
context.
async def create_ticket(args, ctx): ws = ctx.workspace # the caller's workspace user = ctx.user # the authenticated user return f"Created for {user.id}"