Power Actions
Define structured Power Actions with Context, execution identity, and cancellation semantics.
An Action is a Power's explicit business entry point. It consists of a description, optional input
schema/command/API mapping, timeout, and execute function.
import { create_action } from "@downcity/city/power";
import { z } from "zod";
const status = create_action({
description: "Read the current execution scope.",
input_schema: { zod: z.object({}) },
timeout_ms: 30_000,
execute: async ({ context }) => ({
success: true,
data: {
agent_id: context.agent.id,
workspace_id: context.workspace.id,
session_id: context.session?.id ?? null,
turn_id: context.turn?.id ?? null,
tool_call_id: context.call.tool_call_id ?? null,
},
}),
});Each call receives one read-only input, context. It carries the restricted City, Agent,
Workspace, Session, Turn, Config, and Storage handles along with the call identity.
context.call.tool_call_id is the model-assigned Tool Call ID (empty for non-tool entries), and
context.abort_signal is the cancellation signal for this call.
Actions should pass context.abort_signal to network requests, polling, and long-running work.
timeout_ms only triggers cooperative cancellation; underlying operations must observe the signal.
The returned PowerActionResult must be JSON-serializable.
An Action may return additional current-Turn content through messages. Text/file/data Parts with
role: "agent" are appended to the current Agent Message. Text/context/file Parts with role: "user"
are ephemeral input for the next model step and never impersonate a persisted Session Message. The
Session domain consistently uses agent; only the model protocol boundary uses assistant.
command maps Commander input to a payload, while api maps an HTTP request. They do not create a
second business implementation; both end at the same execute function.
Models call Actions through the Power's own tool, whose name is the Power name. Power code may use
context.city.powers.run_action() for another Power registered in City. Application code
creates an explicit execution view with
city.powers.scope({ agent_id: agent.id, workspace_id: workspace.id }) and calls run_action() on it.