Local Agent
Expose City over RPC and HTTP
Use City-owned HTTP and RPC services to expose Agents
Expose City over RPC and HTTP
External services belong to City. Agents remain the execution subjects; City owns the
network listeners and routes requests to its Agents and Workspaces.
pnpm add @downcity/agent @downcity/workspaceStart a City transport
import { Agent, City } from "@downcity/agent";
import { Workspace } from "@downcity/workspace";
const workspace = new Workspace({ id: "project", path: process.cwd() });
const agent = new Agent({ id: "assistant", model });
const city = new City({ workspaces: [workspace] });
city.agents.add(agent);
const rpc = await city.rpc({ host: "127.0.0.1", port: 15314 });
const http = await city.http({ host: "127.0.0.1", port: 5314 });
console.log(rpc.binding()?.url); // rpc://127.0.0.1:15314
console.log(http.binding()?.url); // http://127.0.0.1:5314
await city.close();City owns one HTTP transport and one RPC transport. Both route by Agent ID and Workspace ID:
- HTTP:
http://127.0.0.1:5314/agents/assistant/workspaces/project - RPC:
rpc://127.0.0.1:15314/assistant/project
The protocol is NDJSON for RPC. Authentication, CORS, and other host-level policies belong to the City host.
Start both transports together
await city.listen({
http: { host: "127.0.0.1", port: 5314 },
rpc: { host: "127.0.0.1", port: 15314 },
});
await city.close();city.listen() returns after both listeners are ready. Use city.http() or city.rpc() when
the transports need independent lifecycle control.
Relationship with RemoteAgent
import { RemoteAgent } from "@downcity/agent";
const agent = new RemoteAgent({
url: "http://127.0.0.1:5314/agents/assistant/workspaces/project",
});
const session = await agent.sessions.create();RemoteAgent consumes the City endpoint; it does not create or configure the server-side Agent.