docsruntimetools

Tools

Every tool the agent can call, with signatures and parameters. Cast built-ins, Claude Code SDK tools, peer-dialogue wire tags, and a per-extension index.

Tools come from three places: Cast injects the framework MCP tools below, the Claude Code SDK contributes a fixed set of general-purpose tools, and each active extension contributes its own. Peer dialogue uses wire tags instead of MCP tools — visually, MCP tools carry a coral left rule, wire tags carry amber.

Conversation memory

Search past messages by keyword. Returns previews with IDs — use message_log__read for full text.

Parameters

  • query[string]Full-text search query.
  • optional limit[integer 1–50, default 20]Max results to return.
  • optional channel[string]Filter to a specific channel.
  • optional before[ISO timestamp]Only messages before this timestamp — pagination cursor.
  • optional after[ISO timestamp]Only messages after this timestamp — time-range filter.
  • optional max_tokens[integer 1–1000, default 200]Max tokens per preview snippet.

Returns

Messages (N[, has_more=true, next_cursor=ISO_TIMESTAMP]):
when header line for non-empty results
[ID] [ISO_TIMESTAMP] ROLE: PREVIEW
when one per match; role is "user" or "assistant"
No messages found.
when no matches

Caveats

Scoped to the current participant on this agent. A caller can only see messages addressed to themselves — never crosses identities.

message_log__recent(limit, max_tokens?, before?, after?)

Browse recent messages newest-first without a keyword. Same scope as message_log__search.

Parameters

  • limit[integer 1–50]Number of messages to return.
  • optional max_tokens[integer 1–1000, default 200]Max tokens per preview snippet.
  • optional before[ISO timestamp]Pagination cursor — only messages before this timestamp.
  • optional after[ISO timestamp]Time-range filter — only messages after this timestamp.

Returns

Messages (N[, has_more=true, next_cursor=ISO_TIMESTAMP]):
when header line
[ID] [ISO_TIMESTAMP] ROLE: PREVIEW
when one per row, newest first
No messages found.
when no rows

message_log__read(id, max_tokens?)

Read the full text of a specific message by ID.

Parameters

  • id[integer]Message ID from a search or recent result.
  • optional max_tokens[integer 1–10000, default 2000]Max tokens of body text to return.

Returns

[ID] [ISO_TIMESTAMP] ROLE (CHANNEL):
FULL_TEXT
when found
Message ID not found.
when unknown id
Access denied: message belongs to a different participant.
when cross-participant read attempt

Caveats

Reads are denied if the message belongs to a different participant.

conversation__list_summaries(channel?)

List recent conversations across channels. Shows participant, status, last activity, and summary when available.

Parameters

  • optional channel[string]Filter to one channel.

Returns

- participant: ID, channel: NAME, status: STATUS, last_activity: DURATION[, summary: SUMMARY]
when one per conversation from the past 7 days
No recent conversations.
when no rows

Caveats

May prepend a co-participant visibility note when the current channel hides them, and a privacy reminder when results include other participants' conversations.

conversation__write_summary(summary)

Submit a summary of the current conversation. Stored and visible via conversation__list_summaries.

Parameters

  • summary[string]Concise summary — decisions, action items, outcomes.

Returns

Summary saved.
when success
Cannot submit summary: no conversation context.
when no active conversation

Conversation lifecycle

conversation__end(cooldown_seconds?)

End the current conversation after a cooldown. Cleanup and summary run as usual. If the participant sends a message before the cooldown elapses, the end is cancelled and the agent is notified.

Parameters

  • optional cooldown_seconds[integer 60–86400, default 300]Seconds before the conversation expires. Clamped to the channel's idle_timeout.

Returns

Conversation will end in N seconds. If the participant sends a message, the end will be cancelled.
when always

Caveats

Persistent channels only — single-shot conversations end automatically and have nothing to release.

Cross-conversation push

All pushes are fire-and-forget. If the receiver later rejects the push (ACL revoked, target in draft, etc.) the agent sees a <cast:rejection request="ID"> on a later turn — full details on Runtime › Wire format.

conversation__push_to_channel(channel, text, target_agent?)

Push a turn into another channel. Opens cold or continues an active conversation. Without target_agent the push stays on this agent; with target_agent it crosses to a peer.

Parameters

  • channel[string]Target channel name. For sharded channels, use "name~qualifier" to address a specific sub-conversation.
  • text[string]Message content delivered to the target channel.
  • optional target_agent[string]Peer agent alias (e.g. "knowledge"). Omit for a same-agent push.

Returns

Pushed to CHANNEL for PARTICIPANT. id: REQUEST_ID.
when same-agent success
Pushed to CHANNEL for PARTICIPANT via ALIAS. id: REQUEST_ID.
when cross-agent success
Push failed: REASON
when sync validation fails
<cast:rejection request="ID">REASON</cast:rejection>
when delivery rejected asynchronously; arrives on a later turn

Caveats

Cross-agent pushes hand the originating user to a peer agent and land only if the receiving peer has granted that user access. Passing your own alias is equivalent to omitting.

conversation__push_to_participant(target_participant, channel, text)

Push a turn into a different participant's conversation on this agent. The target participant's runner sees it as a new turn.

Parameters

  • target_participant[string]Target participant address. Use agent__list_participants to enumerate.
  • channel[string]Target channel for that participant. Sharded as "name~qualifier".
  • text[string]Message content.

Returns

Pushed to CHANNEL for TARGET_PARTICIPANT. id: REQUEST_ID.
when success
Push failed: REASON
when sync validation fails
<cast:rejection request="ID">REASON</cast:rejection>
when delivery rejected asynchronously

Caveats

Intra-agent only, no target_agent option. The target must be a user who has access to the target channel, and the channel must let co-participants reach each other.

Peer dialogue

Peer-to-peer messaging uses wire tags rather than MCP tools — the agent writes them inline in its response and the framework routes them. Validation rules and full attribute schema on Runtime › Wire format.

<cast:query target="@PEER"> QUESTION </cast:query>

Ask a peer agent a question and wait for its answer. The body of the tag is the question; the answer arrives on a later turn as <cast:answer request="ID">.

Parameters

  • target[string]Peer alias prefixed with @.

Returns

<cast:answer request="ID">BODY</cast:answer>
when peer replies; arrives as inbound stimulus on a later turn
<cast:pending request="ID">REASON</cast:pending>
when peer's owner has not granted the reach yet; the query is parked, answer or rejection follows
<cast:rejection request="ID">REASON</cast:rejection>
when delivery fails (peer offline, ACL denied)

Caveats

Gated by the peer's q ACL bit toward this agent.

<cast:request target="@PEER"> MESSAGE_BODY </cast:request>

Fire-and-forget message to a peer agent. No reply expected. Returns an id; if delivery is rejected later, a rejection tag carrying that id arrives.

Parameters

  • target[string]Peer alias prefixed with @.

Returns

(nothing inline)
when always — fire-and-forget
<cast:rejection request="ID">REASON</cast:rejection>
when delivery fails; arrives on a later turn

Caveats

Gated by the peer's r ACL bit.

<cast:answer request="ID"> ANSWER_BODY </cast:answer>

Reply to an inbound peer query. The request id is the one carried on the inbound <cast:query>.

Parameters

  • request[string]The id from the inbound query.

Returns

(nothing inline)
when always — answer is routed to the original querier and the request closes server-side

Peer awareness

agent__list_peers()

List peer agents and your relationship with each — who you can query, who can message you, per-channel capability summary. Sharded channels render as name~* — substitute your own qualifier to address a sub-conversation.

Returns

- ALIAS (CANONICAL_ADDRESS)[: DESCRIPTION]
when one block header per peer
  on CHANNEL|CHANNEL~*: CAPABILITIES
when one indented line per channel under each peer
No peer agents configured.
when no peers

agent__list_channels()

List the channels where this conversation's participant is placed — the rooms conversation__push_to_participant can land in. The agent itself and operator surfaces see every configured channel. Sharded channels render as name~*.

Returns

- CHANNEL[~*] — your access: BITS
when one per placed channel; markers for visibility-off and missing config
No channels to list.
when caller is placed nowhere

agent__list_participants(channel?)

List the members of a channel you are placed in, as identities in the exact form push_to_participant accepts, with day-level recency. Scoped by caller standing: a cell can list exactly what the push gate would let it reach, and a query outside its rooms is denied without revealing whether the channel exists. The agent itself and operator surfaces get unfiltered views — and the agent-wide registry when no channel is in play.

Parameters

  • optional channel[string]Optional. Accepts name~qualifier (qualifier ignored — shards share membership). Omitted: the current channel for members, the registry for the agent itself and operator surfaces.

Returns

Members of "CHANNEL":
when room view header
- IDENTITY (last active: YYYY-MM-DD | no session yet)
when one per user member
- IDENTITY — peer agent (request counterparty, not a push target)
when one per placed peer agent
- IDENTITY (last active: ISO_TIMESTAMP)
when registry view rows (under a Participants: header)
You are not authorized on channel "CHANNEL".
when caller not placed there — same wording whether or not the channel exists

Request tracking

request__list()

List open requests for the current channel and participant. Shows both inbound (queries you received) and outbound (queries you sent), with status and age.

Returns

## Outbound (queries you sent)
when section header — present if any outbound rows
- [STATUS] REQUEST_ID → TARGET_AGENT (TARGET_CHANNEL) — AGE
when one per outbound row
## Inbound (queries you received)
when section header — present if any inbound rows
- [STATUS] REQUEST_ID from FROM_AGENT — AGE
when one per inbound row
No requests found for this context.
when no rows in either direction

request__close(request_id)

Close a request by ID. Closing an outbound request means 'I no longer need this answer.' Closing an inbound request means 'I am declining this' and sends a rejection back to the requester.

Parameters

  • request_id[string]The request ID to close.

Returns

Closed outbound request ID.
when closing your own outbound request
Closed inbound request ID and sent rejection.
when declining an inbound request
Request ID not found or already closed.
when unknown or already-closed id
Request ID belongs to a different context.
when wrong channel or participant scope

request__close_all()

Close all open requests for the current channel and participant. Sends rejections for every inbound request.

Returns

Closed N inbound + M outbound requests.
when success
No open requests to close.
when nothing was open

Scheduling

A task is an independent agent session that runs later — it spawns a full agent with all tools. Use tasks for things that need to happen at a future time or on a schedule, not for things you can do now.

task__schedule(prompt, schedule_type, schedule_value, timezone?)

Schedule a deferred or recurring task. Cron schedules use the agent's timezone by default. Bare ISO timestamps (no Z, no offset) are interpreted as agent-local.

Parameters

  • prompt[string]What the agent should do when the task runs. Include all necessary context — wrap output in <cast:internal> to suppress delivery.
  • schedule_type['cron' | 'once']cron = recurring at specific times; once = run once at a specific time.
  • schedule_value[string]cron: "0 10 * * *" (10am local). once: ISO-8601, e.g. "2026-02-01T15:30:00" (agent-local) or with offset "…-05:00".
  • optional timezone[IANA timezone]Override agent's default timezone. Specify only when scheduling for a different tz.

Returns

Task scheduled (ID): SCHEDULE_TYPE - SCHEDULE_VALUE
when success
Invalid cron: "VALUE". …
when cron parse failure
Invalid timestamp: "VALUE". …
when once-mode timestamp parse failure
Invalid timezone: "TIMEZONE". Use IANA format like "America/New_York" or "Europe/London".
when invalid timezone

task__list()

List scheduled tasks (active and paused). Completed and cancelled tasks are not shown.

Returns

Scheduled tasks:
when header line
- [ID] PROMPT_PREVIEW... (SCHEDULE_TYPE: SCHEDULE_VALUE) - STATUS, next: ISO_TIMESTAMP
when one per task
No scheduled tasks.
when no tasks

task__pause(task_id)

Pause a scheduled task. It will not run until resumed.

Parameters

  • task_id[string]The task ID to pause.

Returns

Task ID paused.
when success
Task ID not found.
when unknown id
Unauthorized: cannot pause this task.
when task belongs to a different scope

task__resume(task_id)

Resume a paused task. The next_run is recomputed for cron tasks so stale schedules don't fire immediately.

Parameters

  • task_id[string]The task ID to resume.

Returns

Task ID resumed.
when success
Task ID not found.
when unknown id
Unauthorized: cannot resume this task.
when task belongs to a different scope

task__cancel(task_id)

Cancel and delete a scheduled task.

Parameters

  • task_id[string]The task ID to cancel.

Returns

Task ID cancelled.
when success
Task ID not found.
when unknown id
Unauthorized: cannot cancel this task.
when task belongs to a different scope

task__list_runs(limit?)

View recent task dispatch history. Shows when tasks fired and what they were.

Parameters

  • optional limit[integer 1–100, default 20]Number of recent runs to return.

Returns

Recent task runs:
when header line
- ISO_TIMESTAMP | PROMPT_PREVIEW
when one per dispatch
No task runs found.
when no history

Time

time__now(timezone?)

Get the current time as a human-readable string with day of week, date, time, and timezone. Defaults to the agent's timezone.

Parameters

  • optional timezone[IANA timezone]Override the default, e.g. "America/New_York", "Asia/Tokyo".

Returns

WEEKDAY ISO_TIMESTAMP_WITH_OFFSET
when success
Invalid timezone: "TIMEZONE". …
when tz not recognised

Caveats

Use rather than guessing — the agent's wall clock isn't carried in the conversation context past the system-prompt assembly time.

time__convert(time, from_tz, to_tz)

Convert a time between timezones. Returns formatted times in both. Use for cross-timezone scheduling — never compute offsets yourself (DST and historical offsets aren't safe to derive).

Parameters

  • time[ISO 8601 string]Time to convert.
  • from_tz[IANA timezone]Source timezone.
  • to_tz[IANA timezone]Target timezone.

Returns

FROM_TZ: WEEKDAY ISO_WITH_OFFSET
TO_TZ: WEEKDAY ISO_WITH_OFFSET
when success
Invalid timezone: "TIMEZONE". …
when tz not recognised
Invalid time: "TIME". …
when time parse failure

Filesystem watches

A feed is an ordered, append-only JSONL stream that peers can observe. The framework assigns a monotonic id starting at 1 so watchers can cursor through rows. Use feeds for coordination — meeting points between channels or agents, not as journals or audit logs.

file__append_feed(path, data, meta?)

Append a row to a feed at the given container path. Creates the file if missing; the parent directory must already exist on a writable mount.

Parameters

  • path[string]Container-side path, e.g. /memory/letter.jsonl.
  • data[JSON value]Row content — any JSON-serializable value. Surfaced to humans/transports by convention.
  • optional meta[JSON value]Coordination metadata — agents-only convention, not surfaced to humans.

Returns

Appended row id=N to PATH.
when success
Feed corruption detected at row offset N: REASON. Refusing to append. Operator must repair.
when feed file is corrupted
Parent directory does not exist: HOST_PATH. …
when missing parent dir
No writable mount matches parent of PATH.
when path not on a writable mount
Parent directory is a symlink (rejected for security): HOST_PATH.
when parent resolves to symlink
Parent directory is read-only; cannot append.
when mount is read-only

Caveats

Best-effort, not transactional. Fails closed on corruption (bad parse, missing id, non-monotonic) — operator must repair. Not a journaling tool — for plain JSONL diaries, use Write/Edit directly.

file__watch_feed(path, expiresIn?)

Register a watch on a feed. The framework fires <cast:watch> tags into the conversation when peers append rows. Your own appends are auto-suppressed.

Parameters

  • path[string]Path to the feed — must already exist. Call file__append_feed first to create.
  • optional expiresIn[duration string]Format: number + s|m|h|d. Max 30d. Stored but not enforced — watches persist until removed.

Returns

Watch registered on PATH (lastSeenId=N[, expires ISO_TIMESTAMP]).
when success
Watch limit reached (CURRENT/CAP). Use file__unwatch to free a slot, or raise fileWatch.maxWatchesPerChannel via Configure.
when per-conversation cap hit
Invalid duration: "VALUE". Use format like Ns/Nm/Nh/Nd.
when malformed expiresIn

Caveats

Watches anchor at the feed's current end at registration time — historical rows are not delivered. Per-conversation cap defaults to 3 (configurable via fileWatch.maxWatchesPerChannel).

file__unwatch(path)

Drop a previously registered watch on a feed. Errors if the path is not currently watched in this conversation.

Parameters

  • path[string]Container path matching the original file__watch_feed call.

Returns

Watch on PATH removed.
when success
No watch on PATH for this conversation.
when no such watch

file__list_watches()

List watches active in this conversation. Each entry shows the feed path, the last id observed, when it was registered, and (if set) when it expires.

Returns

Watches:
when header line
- PATH — last id N, registered ISO_TIMESTAMP[, expires ISO_TIMESTAMP]
when one per watch
No watches in this conversation.
when no watches

Python (when configured)

Registered only when the agent has pip.allowed_packages declared in its manifest. There is no pip binary in the container — these tools install into the agent's persistent venv at /home/agent/.python-packages; PYTHONPATH is preconfigured.

pip__install(package, version?, upgrade?)

Install a Python package. Becomes available to all Python scripts in current and future conversations via standard import.

Parameters

  • package[string]Package name, e.g. "duckdb", "pandas". Must be on the agent's allowed_packages list.
  • optional version[string]Version constraint, e.g. "1.2.0", ">=2.0", "<3.0,>=2.1".
  • optional upgrade[boolean, default false]Upgrade to the latest version if already installed.

Returns

Installed PACKAGE VERSION. Available via `import PACKAGE` in Python scripts.
when fresh install or upgrade
PACKAGE is already installed (version VERSION). Use upgrade: true to update.
when package already present and upgrade=false
Package "PACKAGE" is not in the allowed list. Allowed: ALLOWED_LIST
when package outside allowed_packages
pip install failed: STDERR_TAIL
when pip itself errored

Caveats

Runs pip inside a throwaway container built from the agent image — never on the host. Cross-platform safe (wheels match the container, not the host).

pip__list()

List Python packages installed for this agent.

Returns

PACKAGE VERSION
when one per installed package
No Python packages installed. Use pip__install to add packages.
when venv is empty

Claude Code SDK tools

These come from the Claude Code SDK and are always present. They operate inside the container — no host reach. Cast doesn't define their signatures; see the SDK docs for parameter details.

Filesystem: Read, Write, Edit, Glob, Grep, NotebookEdit. Confined to the container's mounts.
Shell: Bash. Host secrets are stripped from subprocess environments before each call.
Web: WebSearch. Runs server-side via the SDK — works even when the container's network is sdk-only.
Sub-agents: Task, TaskOutput, TaskStop. Spawn and manage child Claude sessions inside the same container.
Planning: TodoWrite, Skill, ToolSearch. In-session scratch planning, skill invocation, deferred-tool lookup.

Disabled by Cast: WebFetch (use the web-fetch extension instead — it runs host-side with domain policy, SSRF protection, and cleaned-markdown output), AskUserQuestion (conversations are async — no interactive prompt), and Config (mutates SDK runtime including permission mode).

Extension tools

Each active extension contributes its own tools. Full per-extension signatures live on the extension's own page; this is the index.

calendar — calendar__list, calendar__get, calendar__changes, calendar__create, calendar__update, calendar__delete.
email — email__search, email__fetch, email__send, email__list_folders, email__subscribe, email__unsubscribe, email__list_subscriptions.
web-fetch — web__fetch.
whatsapp — whatsapp__chats, whatsapp__messages, whatsapp__download, whatsapp__send, whatsapp__watch, whatsapp__unwatch, whatsapp__list_watches.