Plugins

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:

  • context is the City-created scope capability with restricted City, Agent, Workspace, Session, Turn, Config, and Storage handles.
  • execution is the call identity with call_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.

Table of Contents