Skip to content

Serving Agency Code

Agency can serve your functions and nodes over MCP or HTTP.

Exporting Functions and Nodes

Only items marked with export are exposed by the serve system:

agency
export idempotent def add(a: number, b: number): number {
  """
  Adds two numbers together.
  @param a - First number
  @param b - Second number
  """
  return a + b
}

export node main(message: string) {
  return process(message)
}

The destructive and idempotent markers are surfaced to clients so they know which tools are safe to re-run. MCP clients see idempotent as an idempotentHint annotation and destructive as a destructiveHint; an unmarked function gets no annotation. The HTTP /list manifest reports the same information as destructive and idempotent booleans (see below).

MCP Server

Start an MCP server over stdio:

bash
agency serve mcp myagent.agency
agency serve mcp myagent.agency --name "My Agent"

Options:

  • --name <name> — Server name (defaults to filename)
  • --transport <transport> — Transport: 'stdio' (default) or 'http' (Streamable HTTP)
  • --port <port> - HTTP port (http transport only, default: 3545)
  • --host <host> - Interface to bind to (http transport only, default: 127.0.0.1, loopback only). Use 0.0.0.0 to expose externally (requires --api-key/--api-key-env).
  • --path <path> - Endpoint path the MCP server is mounted at (http transport only, default: /mcp)
  • --api-key <key> - API key for authentication (http transport only). NOT recommended: visible in process listings. Prefer --api-key-env.
  • --api-key-env <name> - Name of the environment variable to read the API key from (http transport only). For --standalone, the bundle reads this env var at runtime (default: API_KEY).
  • --standalone - Generate a standalone server.js file

HTTP Server

Start an HTTP REST server:

bash
agency serve http myagent.agency
agency serve http myagent.agency --port 8080
agency serve http myagent.agency --api-key my-secret-key

The http command has similar options as the mcp command. Run agency serve http --help for more information.

Routes

GET /list — Returns a manifest of available functions and nodes:

json
{
  "functions": [
    { "name": "add", "description": "Adds two numbers together.", "destructive": false, "idempotent": true }
  ],
  "nodes": [
    { "name": "main", "parameters": ["message"] }
  ]
}

POST /function/:name — Call an exported function:

bash
curl -X POST http://localhost:3545/function/add \
  -H 'Content-Type: application/json' \
  -d '{"a": 3, "b": 4}'

Response:

json
{ "success": true, "value": 7 }

POST /node/:name — Run an exported node:

bash
curl -X POST http://localhost:3545/node/main \
  -H 'Content-Type: application/json' \
  -d '{"message": "hello"}'

Response:

json
{ "success": true, "value": { "result": "processed hello" } }

Interrupts

If a node triggers an interrupt during execution, the response includes the interrupt data:

json
{
  "success": true,
  "value": {
    "interrupts": [
      { "type": "interrupt", "effect": "std::read", "message": "Do you approve?" }
    ]
  }
}

To resume after an interrupt, use POST /resume with the interrupts and your responses:

bash
curl -X POST http://localhost:3545/resume \
  -H 'Content-Type: application/json' \
  -d '{
    "interrupts": [... the interrupts array from above ...],
    "responses": [{"type": "approve"}]
  }'

The responses should correspond positionally to the interrupts.

Authentication

When --api-key is set, all requests must include a Bearer token:

bash
curl -H 'Authorization: Bearer my-secret-key' http://localhost:3545/list

Requests without a valid token receive a 401 Unauthorized response.

Standalone Mode

Generate a self-contained server file.

bash
agency serve http myagent.agency --standalone

This produces a bundled .server.js file. Users can run this file directly with Node, without needing Agency installed.

Also see pack.