Worked example: an agent authoring on the agent server

Embed
Preview of the card
<a href="https://forumulate.com/reference/agent-workflow"><img src="https://forumulate.com/reference/_api/public/orgs/046a9bc0-d530-43ae-9bae-af7945008cda/spaces/8042f004-e3d9-445f-b7a4-b6c1f86836e6/pages/c9463b44-ebef-4c9e-b30a-b0152cd5575d/social-card.svg?v=3e7ae33eec8b" alt="Worked example: an agent authoring on the agent server" width="600" height="315"></a>

This walks one full task end to end, naming the real tools in sequence. Every call is a tools/call against POST /orgs/{orgId}/mcp with a Bearer cft_… token (needs the write scope to author).

1. Handshake and discover the tools

{ "jsonrpc": "2.0", "id": 1, "method": "initialize",
  "params": { "protocolVersion": "2025-06-18" } }

Then tools/list, and — recommended — read the two resources so you know the map:

{ "jsonrpc": "2.0", "id": 2, "method": "resources/read",
  "params": { "uri": "forumulate://space-types" } }

2. Find the space and learn its shape

{ "method": "tools/call",
  "params": { "name": "list_spaces", "arguments": {} } }

Pick the spaceId you want, then ask what one piece of it is made of — its named sections, which are required, its presets, and a ready-to-use JSON Schema:

{ "method": "tools/call", "params": {
  "name": "get_space_shape",
  "arguments": { "spaceId": "spc_docs" } } }

3. See what is already there

{ "method": "tools/call", "params": {
  "name": "list_items",
  "arguments": { "spaceId": "spc_docs", "limit": 50 } } }

4. Create a piece, filling the declared sections

Use the section keys and preset name from get_space_shape. Anything belonging to no section goes in body. The reply tells you which required sections are still empty.

{ "method": "tools/call", "params": {
  "name": "create_item",
  "arguments": {
    "spaceId": "spc_docs",
    "title": "Connecting over SSO",
    "preset": "how-to",
    "sections": {
      "overview": "Set up SAML in ten minutes.",
      "steps": "1. Open Settings → Auth\n2. …"
    }
  } } }

If a required section came back empty, fill it (idempotent):

{ "method": "tools/call", "params": {
  "name": "update_section",
  "arguments": { "spaceId": "spc_docs", "itemId": "itm_123",
    "key": "prerequisites", "markdown": "An admin account." } } }

Set any declared structured fields with set_item_fields (or set_page_fields for a docs page's metadata).

5. Publish

{ "method": "tools/call", "params": {
  "name": "publish_item",
  "arguments": { "spaceId": "spc_docs", "itemId": "itm_123" } } }

6. A studio write: triage a forum topic

Studio writes need the target's id first. For a forum category, list the space's structural pieces with list_entities:

{ "method": "tools/call", "params": {
  "name": "list_entities",
  "arguments": { "spaceId": "spc_forum", "kind": "categories" } } }

Find the topic with list_items (or search), then file it under a category:

{ "method": "tools/call", "params": {
  "name": "set_topic_category",
  "arguments": { "spaceId": "spc_forum",
    "topicId": "top_88", "categoryId": "cat_bugs" } } }

Other studio writes follow the same read-then-write pattern: moderate_topic (pin/close/accept an answer), set_roadmap_status (move a request into a lane), edit_status_component (update a monitor or incident — get its id from list_entities with kind: "monitors" or "incidents").

7. Anything the tools do not cover

Read forumulate://openapi, then drive the route with call_api — same credentials, same guards:

{ "method": "tools/call", "params": {
  "name": "call_api",
  "arguments": { "method": "GET",
    "path": "/orgs/{orgId}/spaces/spc_forum/members" } } }

Paths must stay within the allowlist and this organization (see the tools page).

The Forumulate teamUpdated