Plugin Actions
Define structured Plugin Actions with Context, execution identity, and cancellation semantics.
Plugin Actions
An Action is a Plugin'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/plugin";
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, execution }) => ({
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,
call_id: execution.call_id,
},
}),
});Each call receives two read-only inputs:
contextis the City-created scope capability with restricted City, Agent, Workspace, Session, Turn, Config, and Storage handles.executionis the call identity withcall_id,abort_signal, optional Session scope, and Step snapshot.
Actions should pass execution.abort_signal to network requests, polling, and long-running work.
timeout_ms only triggers cooperative cancellation; underlying operations must observe the signal.
The returned PluginActionResult 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 current Session's plugin_call Tool. Plugin code may use
context.city.plugins.run_action() for another Plugin registered in City. Application code
creates an explicit execution view with
city.plugins.scope({ agent_id: agent.id, workspace_id: workspace.id }) and calls run_action() on it.