Power Call Surfaces
Distinguish City management, Workspace execution, PowerContext, and the Power model tools.
Powers expose four call surfaces for different callers:
| Surface | Caller | Purpose |
|---|---|---|
city.powers | Host application | Add or remove unique instances and invoke host/config actions |
city.powers.scope({ agent_id: agent.id, workspace_id: workspace.id }) | Host execution code | Call Actions, Availability, or Hooks in one Agent/Workspace scope |
context.city.powers | Power code | Call another Power Action, pipeline, or effect in the current scope |
skill | Model in a Session | Call a Power Action provided by City |
City management surface
city.powers.add(skill_power);
console.log(city.powers.snapshots());
await city.powers.remove("skill");city.powers.invoke() and invoke_config() call host-management Actions registered during start();
they are not Session execution Actions.
Workspace execution surface
const result = await city.powers.scope({ agent_id: agent.id, workspace_id: workspace.id }).run_action({
power: "skill",
action: "lookup",
payload: { name: "frontend-design" },
});This surface explicitly binds an Agent and Workspace, allowing City to create the correct
PowerContext.
PowerContext
const result = await context.city.powers.run_action({
power: "skill",
action: "list",
payload: {},
});
await context.city.powers.effect("audit.observe", result.data ?? null);context.session, context.agent.sessions, and context.workspace are directly callable handles.
IDs are reserved for stable identity and serialization.
Model Tool
Each Power with Actions compiles into its own model-facing tool whose name is the Power name. There is no
shared plugin_call entry: the model calls the skill tool here, and ai for the City-owned image and
speech capabilities.
skill({
action: "lookup",
args: { name: "frontend-design" },
});The Tool is always bound to the current Session's Agent/Workspace execution lease and cannot observe another Agent's bindings.