{"$schema":"https://wellknown.network/schemas/agent-record-v1.json","schemaVersion":"1","id":"ag_78yeax9hy4d5","handle":"agent4-io","url":"https://wellknown.network/agents/agent4-io","links":{"self":"https://wellknown.network/agents/agent4-io/record.json","html":"https://wellknown.network/agents/agent4-io","markdown":"https://wellknown.network/agents/agent4-io/record.md","api":"https://wellknown.network/api/v1/agents/agent4-io","status":"https://wellknown.network/api/v1/agents/agent4-io/status","claim":"https://wellknown.network/agents/agent4-io/claim","claimApi":"https://wellknown.network/api/v1/claims","claimDescriptor":"https://wellknown.network/agents/agent4-io/claim.json","badge":"https://wellknown.network/agents/agent4-io/badge.svg","openapi":"https://wellknown.network/openapi.json"},"ard":{"identifier":"urn:air:api.agent4.io:server:agent4-io","type":"application/mcp-server-card+json"},"kind":"mcp_server","declared":{"name":"agent4.io","summary":"Build and run grounded business agents over MCP: agents, knowledge bases, skills, Storylines.","description":"Build and run grounded business agents over MCP: agents, knowledge bases, skills, Storylines.","publisher":{"name":"io.agent4","url":null},"homepage":"https://agent4.io","repository":null,"version":"1.4.0","license":null,"protocols":["mcp"],"tags":[],"pricing":null,"endpoints":[{"url":"https://api.agent4.io/v1/mcp","type":"mcp_streamable_http","auth":null,"probeable":true}],"skills":null,"tools":null,"extra":{"updatedAt":"2026-07-30T23:59:24.588172Z","publishedAt":"2026-07-30T23:59:24.588172Z","registryName":"io.agent4/agent4-tenant"},"attribution":{"kind":"mcp_registry","name":"mcp_registry","summary":"mcp_registry","version":"mcp_registry","description":"mcp_registry","homepageUrl":"mcp_registry","publisherName":"mcp_registry"}},"derived":{"capabilities":[{"slug":"content.writing","name":"Writing & Editing","confidence":1,"provenance":"derived"},{"slug":"ai.prompting","name":"Prompt Management","confidence":1,"provenance":"derived"},{"slug":"automation.workflows","name":"Workflow Automation","confidence":0.977,"provenance":"derived"},{"slug":"code.refactoring","name":"Refactoring","confidence":0.54,"provenance":"derived"},{"slug":"security.identity","name":"Identity & Access","confidence":0.525,"provenance":"derived"}],"categories":["ai","automation","code","content","security"]},"observed":{"status":"live","statusReason":"Responded 13h ago.","lastOkAt":"2026-09-06T02:27:11.136Z","lastProbedAt":"2026-09-06T02:27:11.136Z","statusComputedAt":"2026-09-06T02:28:26.942Z","reliability30d":{"probes":1,"successRate":1,"p50Ms":147},"latestObservations":[{"at":"2026-09-06T11:28:46.315Z","kind":"mcp_initialize","ok":true,"httpStatus":200,"latencyMs":140,"error":null,"detail":{"tools":[{"name":"list_agents","description":"List all agents in this tenant (name + published state)."},{"name":"get_agent","description":"Get one agent's full configuration (soul/task/tools/skills/knowledge_bases/model/params)."},{"name":"create_agent","description":"Create an agent.\n\n    `name` is lower-cased on save — it is a key, not a display name.\n\n    soul = persona/identity; task = duties and boundaries; tools = tool-"},{"name":"update_agent","description":"Update **part** of an agent — fields you don't pass stay as they are.\n\n    ⚠️ List-field semantics, don't mix them up: `tools=[...]` / `skills=[...]` /\n    `kno"},{"name":"list_tools","description":"List tool names assignable to agents, with their descriptions (incl. the tenant's connected MCP tools)."},{"name":"list_mcp_servers","description":"List the MCP servers connected in this tenant's tool library (read-only; secret fields omitted)."},{"name":"create_share","description":"Create a **share / integration entry point** for an agent — this is how end users actually reach it.\n\n    **`published=True` only means \"visible\", not \"reachabl"},{"name":"list_shares","description":"List an agent's shares (token / label / disabled / chat link / embed URL / appearance config).\n\n    When the top-level `pretty_url` is non-empty it is the prefe"},{"name":"configure_share","description":"Configure this share — its name and its **appearance** — fields you don't pass stay as they\n    are (server-side partial merge).\n\n    - `label`: the name at the"},{"name":"set_pwa_branding","description":"Configure a specific **agent's** PWA branding and install experience (applies to that\n    agent's `/s/` standalone chat pages — what gets installed to the home "},{"name":"set_custom_domain","description":"Bind the client's own domain to this tenant's chat pages: `https://chat.client.com/` serves\n    the tenant's branded page (or a specific agent's chat), the addr"},{"name":"list_skills","description":"List this tenant's skills."},{"name":"get_skill","description":"Get one skill's full content (including the complete instructions text)."},{"name":"create_skill","description":"Create a skill. description = \"when to use\" (goes into the system prompt, keep it short);\n    instructions = the detailed guide (fetched on demand via load_skil"},{"name":"update_skill","description":"Update part of a skill — fields you don't pass stay as they are (server-side PATCH merge,\n    no GET+PUT round-trip).\n\n    ⚠️ `tools=[...]` is **full-list repla"},{"name":"test_skill_trigger","description":"Reality-check whether your prompts actually trigger tool calls (dry-run) — run this after\n    writing/changing a skill instead of counting corpses in production"},{"name":"list_knowledge_bases","description":"List this tenant's knowledge bases (with doc/chunk counts and relevance cutoff)."},{"name":"get_knowledge_base","description":"Get one knowledge base's configuration (including the full instructions text shown to the model)."},{"name":"create_knowledge_base","description":"Create a knowledge base.\n\n    **Write `description` — it is what routes questions to this base.** Before each answer the\n    platform reads every attached base'"},{"name":"update_knowledge_base","description":"Update part of a knowledge base — fields you don't pass stay as they are (server-side PATCH merge)."},{"name":"add_knowledge_text","description":"Add a **text** document to a knowledge base (chunking + embedding happen synchronously;\n    returns the real chunk count).\n\n    For **local files** (pdf/docx…) "},{"name":"add_knowledge_file","description":"Add a local file's content to a knowledge base (txt/md/html/pdf/docx).\n\n    **This MCP runs on the platform server and cannot read paths on YOUR machine.** For "},{"name":"search_knowledge_base","description":"Search this knowledge base; returns matching chunks with distances.\n\n    Uses **exactly the same retrieval path as real conversations** — use it to validate the"},{"name":"build_knowledge_index","description":"Build (or rebuild) the structured index for a knowledge base — the second leg beside vector search.\n\n    Vector search answers \"what does this passage say\". It "},{"name":"get_knowledge_index","description":"Show the structured index profile: per column coverage, type, numeric range, top values, warnings.\n\n    **The warnings are the point.** On a real 4,500-document"},{"name":"patch_knowledge_index","description":"Change the structured index schema from one sentence of plain language.\n\n    Example requests: \"also track the author so users can find other books by them\", \"I"},{"name":"improve_prompt","description":"Rewrite a field's text to work better as an AI system prompt; returns the improved text.\n\n    field ∈ persona | task | greeting | storyline_task | storyline_ope"},{"name":"diagnose_prompt","description":"Read a field and return a list of **specific** improvement suggestions (string array).\n\n    field: same values as improve_prompt. current = the text to diagnose"},{"name":"test_planner_trigger","description":"Dry-run the Dynamic Planner's escalation judge: would these messages be offered a\n    step-by-step plan? Use it after editing the agent's `task`, since the task"},{"name":"preview_plan","description":"Generate a plan for a goal and return it for review **without persisting anything** — no\n    temporary storyline, no enrollment, no user affected. Use it to ins"},{"name":"usage_stats","description":"Usage statistics. group ∈ total | agent | user | space | day | model.\n\n    Metadata only — token counts and event counts, never any conversation content.\n    Us"},{"name":"tenant_info","description":"This tenant's basic info and quota (plus custom-domain binding status, if any)."},{"name":"search_agent4_docs","description":"Search agent4.io's own product docs — concepts (what a thing *is*) and cookbook recipes (which\n    tool to *call*). Use when you're unsure how an agent4.io feat"},{"name":"list_end_users","description":"List this tenant's **end users** (the people chatting with your agents) — roster only,\n    never any conversation content.\n\n    Each user carries: display name,"},{"name":"get_end_user","description":"Get one end user's detail: basic profile (name, contact email/phone, city, timezone) + their\n    spaces.\n\n    Never any conversation content. Carries a `console"},{"name":"list_user_sessions","description":"List one end user's **sessions** — metadata only: agent, title (AI summary), message count,\n    tokens, timestamps.\n\n    **Message bodies are not returned.** Tr"},{"name":"list_page_contexts","description":"List all page playbooks of this tenant (with match rules, greeting mode, position)."},{"name":"upsert_page_context","description":"Create or fully replace a page playbook.\n\n    `context` is the page background the **server** injects for the agent — write \"who lands on\n    this page, what th"},{"name":"resolve_page_context","description":"Given a URL (or key), show which playbook it resolves to — always verify after writing a\n    match rule.\n\n    Globs make it easy to write rules that \"look right"},{"name":"page_context_stats","description":"Open counts and suggested-question click counts per playbook — find copy nobody clicks."},{"name":"list_storylines","description":"List this tenant's storylines (optionally filtered by agent). Includes state, version, default flag."},{"name":"get_storyline","description":"Get one storyline's full definition (whole graph + profile_schema + top-level fields)."},{"name":"create_storyline","description":"Create a storyline draft. After creating, self-check with validate_storyline, then\n    publish_storyline.\n\n    user_visibility — what the end user sees of their"},{"name":"update_storyline","description":"Update **part** of a storyline draft — fields you don't pass stay as they are (GET-then-merge\n    on top of a full PUT underneath).\n\n    concurrency: \"user\" = p"},{"name":"validate_storyline","description":"Validate the storyline graph (entry / dead ends / unreachable / dangling / cross-line targets\n    / rule dimensions). Returns {ok, errors}. Must pass before pub"},{"name":"publish_storyline","description":"Publish a storyline: validates first (blocking errors → 422), then freezes an immutable\n    version and marks it published."},{"name":"unpublish_storyline","description":"Unpublish (archive): no more auto-enrolment; in-flight users silently degrade to the plain\n    agent on their next turn (progress kept — re-publishing resumes i"},{"name":"clone_storyline","description":"Clone a storyline into a new draft (new key, unpublished, doesn't claim default, no chain\n    pointer) for tweaking."},{"name":"export_storyline","description":"Export a portable storyline JSON (schema_version + definition; no tenant/version/id) for\n    backup, migration or re-import."},{"name":"import_storyline","description":"Import an exported storyline JSON as a draft. **Artifacts like \"generate a storyline from a\n    novel / source material\" land here.**\n\n    payload = the structu"}],"toolCount":50,"serverName":"agent4-io","capabilities":["experimental","prompts","resources","tools"],"serverVersion":"","protocolVersion":"2025-06-18"}},{"at":"2026-09-06T02:27:11.136Z","kind":"mcp_initialize","ok":true,"httpStatus":200,"latencyMs":147,"error":null,"detail":{"tools":[{"name":"list_agents","description":"List all agents in this tenant (name + published state)."},{"name":"get_agent","description":"Get one agent's full configuration (soul/task/tools/skills/knowledge_bases/model/params)."},{"name":"create_agent","description":"Create an agent.\n\n    `name` is lower-cased on save — it is a key, not a display name.\n\n    soul = persona/identity; task = duties and boundaries; tools = tool-"},{"name":"update_agent","description":"Update **part** of an agent — fields you don't pass stay as they are.\n\n    ⚠️ List-field semantics, don't mix them up: `tools=[...]` / `skills=[...]` /\n    `kno"},{"name":"list_tools","description":"List tool names assignable to agents, with their descriptions (incl. the tenant's connected MCP tools)."},{"name":"list_mcp_servers","description":"List the MCP servers connected in this tenant's tool library (read-only; secret fields omitted)."},{"name":"create_share","description":"Create a **share / integration entry point** for an agent — this is how end users actually reach it.\n\n    **`published=True` only means \"visible\", not \"reachabl"},{"name":"list_shares","description":"List an agent's shares (token / label / disabled / chat link / embed URL / appearance config).\n\n    When the top-level `pretty_url` is non-empty it is the prefe"},{"name":"configure_share","description":"Configure this share — its name and its **appearance** — fields you don't pass stay as they\n    are (server-side partial merge).\n\n    - `label`: the name at the"},{"name":"set_pwa_branding","description":"Configure a specific **agent's** PWA branding and install experience (applies to that\n    agent's `/s/` standalone chat pages — what gets installed to the home "},{"name":"set_custom_domain","description":"Bind the client's own domain to this tenant's chat pages: `https://chat.client.com/` serves\n    the tenant's branded page (or a specific agent's chat), the addr"},{"name":"list_skills","description":"List this tenant's skills."},{"name":"get_skill","description":"Get one skill's full content (including the complete instructions text)."},{"name":"create_skill","description":"Create a skill. description = \"when to use\" (goes into the system prompt, keep it short);\n    instructions = the detailed guide (fetched on demand via load_skil"},{"name":"update_skill","description":"Update part of a skill — fields you don't pass stay as they are (server-side PATCH merge,\n    no GET+PUT round-trip).\n\n    ⚠️ `tools=[...]` is **full-list repla"},{"name":"test_skill_trigger","description":"Reality-check whether your prompts actually trigger tool calls (dry-run) — run this after\n    writing/changing a skill instead of counting corpses in production"},{"name":"list_knowledge_bases","description":"List this tenant's knowledge bases (with doc/chunk counts and relevance cutoff)."},{"name":"get_knowledge_base","description":"Get one knowledge base's configuration (including the full instructions text shown to the model)."},{"name":"create_knowledge_base","description":"Create a knowledge base.\n\n    **Write `description` — it is what routes questions to this base.** Before each answer the\n    platform reads every attached base'"},{"name":"update_knowledge_base","description":"Update part of a knowledge base — fields you don't pass stay as they are (server-side PATCH merge)."},{"name":"add_knowledge_text","description":"Add a **text** document to a knowledge base (chunking + embedding happen synchronously;\n    returns the real chunk count).\n\n    For **local files** (pdf/docx…) "},{"name":"add_knowledge_file","description":"Add a local file's content to a knowledge base (txt/md/html/pdf/docx).\n\n    **This MCP runs on the platform server and cannot read paths on YOUR machine.** For "},{"name":"search_knowledge_base","description":"Search this knowledge base; returns matching chunks with distances.\n\n    Uses **exactly the same retrieval path as real conversations** — use it to validate the"},{"name":"build_knowledge_index","description":"Build (or rebuild) the structured index for a knowledge base — the second leg beside vector search.\n\n    Vector search answers \"what does this passage say\". It "},{"name":"get_knowledge_index","description":"Show the structured index profile: per column coverage, type, numeric range, top values, warnings.\n\n    **The warnings are the point.** On a real 4,500-document"},{"name":"patch_knowledge_index","description":"Change the structured index schema from one sentence of plain language.\n\n    Example requests: \"also track the author so users can find other books by them\", \"I"},{"name":"improve_prompt","description":"Rewrite a field's text to work better as an AI system prompt; returns the improved text.\n\n    field ∈ persona | task | greeting | storyline_task | storyline_ope"},{"name":"diagnose_prompt","description":"Read a field and return a list of **specific** improvement suggestions (string array).\n\n    field: same values as improve_prompt. current = the text to diagnose"},{"name":"test_planner_trigger","description":"Dry-run the Dynamic Planner's escalation judge: would these messages be offered a\n    step-by-step plan? Use it after editing the agent's `task`, since the task"},{"name":"preview_plan","description":"Generate a plan for a goal and return it for review **without persisting anything** — no\n    temporary storyline, no enrollment, no user affected. Use it to ins"},{"name":"usage_stats","description":"Usage statistics. group ∈ total | agent | user | space | day | model.\n\n    Metadata only — token counts and event counts, never any conversation content.\n    Us"},{"name":"tenant_info","description":"This tenant's basic info and quota (plus custom-domain binding status, if any)."},{"name":"search_agent4_docs","description":"Search agent4.io's own product docs — concepts (what a thing *is*) and cookbook recipes (which\n    tool to *call*). Use when you're unsure how an agent4.io feat"},{"name":"list_end_users","description":"List this tenant's **end users** (the people chatting with your agents) — roster only,\n    never any conversation content.\n\n    Each user carries: display name,"},{"name":"get_end_user","description":"Get one end user's detail: basic profile (name, contact email/phone, city, timezone) + their\n    spaces.\n\n    Never any conversation content. Carries a `console"},{"name":"list_user_sessions","description":"List one end user's **sessions** — metadata only: agent, title (AI summary), message count,\n    tokens, timestamps.\n\n    **Message bodies are not returned.** Tr"},{"name":"list_page_contexts","description":"List all page playbooks of this tenant (with match rules, greeting mode, position)."},{"name":"upsert_page_context","description":"Create or fully replace a page playbook.\n\n    `context` is the page background the **server** injects for the agent — write \"who lands on\n    this page, what th"},{"name":"resolve_page_context","description":"Given a URL (or key), show which playbook it resolves to — always verify after writing a\n    match rule.\n\n    Globs make it easy to write rules that \"look right"},{"name":"page_context_stats","description":"Open counts and suggested-question click counts per playbook — find copy nobody clicks."},{"name":"list_storylines","description":"List this tenant's storylines (optionally filtered by agent). Includes state, version, default flag."},{"name":"get_storyline","description":"Get one storyline's full definition (whole graph + profile_schema + top-level fields)."},{"name":"create_storyline","description":"Create a storyline draft. After creating, self-check with validate_storyline, then\n    publish_storyline.\n\n    user_visibility — what the end user sees of their"},{"name":"update_storyline","description":"Update **part** of a storyline draft — fields you don't pass stay as they are (GET-then-merge\n    on top of a full PUT underneath).\n\n    concurrency: \"user\" = p"},{"name":"validate_storyline","description":"Validate the storyline graph (entry / dead ends / unreachable / dangling / cross-line targets\n    / rule dimensions). Returns {ok, errors}. Must pass before pub"},{"name":"publish_storyline","description":"Publish a storyline: validates first (blocking errors → 422), then freezes an immutable\n    version and marks it published."},{"name":"unpublish_storyline","description":"Unpublish (archive): no more auto-enrolment; in-flight users silently degrade to the plain\n    agent on their next turn (progress kept — re-publishing resumes i"},{"name":"clone_storyline","description":"Clone a storyline into a new draft (new key, unpublished, doesn't claim default, no chain\n    pointer) for tweaking."},{"name":"export_storyline","description":"Export a portable storyline JSON (schema_version + definition; no tenant/version/id) for\n    backup, migration or re-import."},{"name":"import_storyline","description":"Import an exported storyline JSON as a draft. **Artifacts like \"generate a storyline from a\n    novel / source material\" land here.**\n\n    payload = the structu"}],"toolCount":50,"serverName":"agent4-io","capabilities":["experimental","prompts","resources","tools"],"serverVersion":"","protocolVersion":"2025-06-18"}}],"tools":[{"name":"list_agents","description":"List all agents in this tenant (name + published state)."},{"name":"get_agent","description":"Get one agent's full configuration (soul/task/tools/skills/knowledge_bases/model/params)."},{"name":"create_agent","description":"Create an agent.\n\n    `name` is lower-cased on save — it is a key, not a display name.\n\n    soul = persona/identity; task = duties and boundaries; tools = tool-"},{"name":"update_agent","description":"Update **part** of an agent — fields you don't pass stay as they are.\n\n    ⚠️ List-field semantics, don't mix them up: `tools=[...]` / `skills=[...]` /\n    `kno"},{"name":"list_tools","description":"List tool names assignable to agents, with their descriptions (incl. the tenant's connected MCP tools)."},{"name":"list_mcp_servers","description":"List the MCP servers connected in this tenant's tool library (read-only; secret fields omitted)."},{"name":"create_share","description":"Create a **share / integration entry point** for an agent — this is how end users actually reach it.\n\n    **`published=True` only means \"visible\", not \"reachabl"},{"name":"list_shares","description":"List an agent's shares (token / label / disabled / chat link / embed URL / appearance config).\n\n    When the top-level `pretty_url` is non-empty it is the prefe"},{"name":"configure_share","description":"Configure this share — its name and its **appearance** — fields you don't pass stay as they\n    are (server-side partial merge).\n\n    - `label`: the name at the"},{"name":"set_pwa_branding","description":"Configure a specific **agent's** PWA branding and install experience (applies to that\n    agent's `/s/` standalone chat pages — what gets installed to the home "},{"name":"set_custom_domain","description":"Bind the client's own domain to this tenant's chat pages: `https://chat.client.com/` serves\n    the tenant's branded page (or a specific agent's chat), the addr"},{"name":"list_skills","description":"List this tenant's skills."},{"name":"get_skill","description":"Get one skill's full content (including the complete instructions text)."},{"name":"create_skill","description":"Create a skill. description = \"when to use\" (goes into the system prompt, keep it short);\n    instructions = the detailed guide (fetched on demand via load_skil"},{"name":"update_skill","description":"Update part of a skill — fields you don't pass stay as they are (server-side PATCH merge,\n    no GET+PUT round-trip).\n\n    ⚠️ `tools=[...]` is **full-list repla"},{"name":"test_skill_trigger","description":"Reality-check whether your prompts actually trigger tool calls (dry-run) — run this after\n    writing/changing a skill instead of counting corpses in production"},{"name":"list_knowledge_bases","description":"List this tenant's knowledge bases (with doc/chunk counts and relevance cutoff)."},{"name":"get_knowledge_base","description":"Get one knowledge base's configuration (including the full instructions text shown to the model)."},{"name":"create_knowledge_base","description":"Create a knowledge base.\n\n    **Write `description` — it is what routes questions to this base.** Before each answer the\n    platform reads every attached base'"},{"name":"update_knowledge_base","description":"Update part of a knowledge base — fields you don't pass stay as they are (server-side PATCH merge)."},{"name":"add_knowledge_text","description":"Add a **text** document to a knowledge base (chunking + embedding happen synchronously;\n    returns the real chunk count).\n\n    For **local files** (pdf/docx…) "},{"name":"add_knowledge_file","description":"Add a local file's content to a knowledge base (txt/md/html/pdf/docx).\n\n    **This MCP runs on the platform server and cannot read paths on YOUR machine.** For "},{"name":"search_knowledge_base","description":"Search this knowledge base; returns matching chunks with distances.\n\n    Uses **exactly the same retrieval path as real conversations** — use it to validate the"},{"name":"build_knowledge_index","description":"Build (or rebuild) the structured index for a knowledge base — the second leg beside vector search.\n\n    Vector search answers \"what does this passage say\". It "},{"name":"get_knowledge_index","description":"Show the structured index profile: per column coverage, type, numeric range, top values, warnings.\n\n    **The warnings are the point.** On a real 4,500-document"},{"name":"patch_knowledge_index","description":"Change the structured index schema from one sentence of plain language.\n\n    Example requests: \"also track the author so users can find other books by them\", \"I"},{"name":"improve_prompt","description":"Rewrite a field's text to work better as an AI system prompt; returns the improved text.\n\n    field ∈ persona | task | greeting | storyline_task | storyline_ope"},{"name":"diagnose_prompt","description":"Read a field and return a list of **specific** improvement suggestions (string array).\n\n    field: same values as improve_prompt. current = the text to diagnose"},{"name":"test_planner_trigger","description":"Dry-run the Dynamic Planner's escalation judge: would these messages be offered a\n    step-by-step plan? Use it after editing the agent's `task`, since the task"},{"name":"preview_plan","description":"Generate a plan for a goal and return it for review **without persisting anything** — no\n    temporary storyline, no enrollment, no user affected. Use it to ins"},{"name":"usage_stats","description":"Usage statistics. group ∈ total | agent | user | space | day | model.\n\n    Metadata only — token counts and event counts, never any conversation content.\n    Us"},{"name":"tenant_info","description":"This tenant's basic info and quota (plus custom-domain binding status, if any)."},{"name":"search_agent4_docs","description":"Search agent4.io's own product docs — concepts (what a thing *is*) and cookbook recipes (which\n    tool to *call*). Use when you're unsure how an agent4.io feat"},{"name":"list_end_users","description":"List this tenant's **end users** (the people chatting with your agents) — roster only,\n    never any conversation content.\n\n    Each user carries: display name,"},{"name":"get_end_user","description":"Get one end user's detail: basic profile (name, contact email/phone, city, timezone) + their\n    spaces.\n\n    Never any conversation content. Carries a `console"},{"name":"list_user_sessions","description":"List one end user's **sessions** — metadata only: agent, title (AI summary), message count,\n    tokens, timestamps.\n\n    **Message bodies are not returned.** Tr"},{"name":"list_page_contexts","description":"List all page playbooks of this tenant (with match rules, greeting mode, position)."},{"name":"upsert_page_context","description":"Create or fully replace a page playbook.\n\n    `context` is the page background the **server** injects for the agent — write \"who lands on\n    this page, what th"},{"name":"resolve_page_context","description":"Given a URL (or key), show which playbook it resolves to — always verify after writing a\n    match rule.\n\n    Globs make it easy to write rules that \"look right"},{"name":"page_context_stats","description":"Open counts and suggested-question click counts per playbook — find copy nobody clicks."},{"name":"list_storylines","description":"List this tenant's storylines (optionally filtered by agent). Includes state, version, default flag."},{"name":"get_storyline","description":"Get one storyline's full definition (whole graph + profile_schema + top-level fields)."},{"name":"create_storyline","description":"Create a storyline draft. After creating, self-check with validate_storyline, then\n    publish_storyline.\n\n    user_visibility — what the end user sees of their"},{"name":"update_storyline","description":"Update **part** of a storyline draft — fields you don't pass stay as they are (GET-then-merge\n    on top of a full PUT underneath).\n\n    concurrency: \"user\" = p"},{"name":"validate_storyline","description":"Validate the storyline graph (entry / dead ends / unreachable / dangling / cross-line targets\n    / rule dimensions). Returns {ok, errors}. Must pass before pub"},{"name":"publish_storyline","description":"Publish a storyline: validates first (blocking errors → 422), then freezes an immutable\n    version and marks it published."},{"name":"unpublish_storyline","description":"Unpublish (archive): no more auto-enrolment; in-flight users silently degrade to the plain\n    agent on their next turn (progress kept — re-publishing resumes i"},{"name":"clone_storyline","description":"Clone a storyline into a new draft (new key, unpublished, doesn't claim default, no chain\n    pointer) for tweaking."},{"name":"export_storyline","description":"Export a portable storyline JSON (schema_version + definition; no tenant/version/id) for\n    backup, migration or re-import."},{"name":"import_storyline","description":"Import an exported storyline JSON as a draft. **Artifacts like \"generate a storyline from a\n    novel / source material\" land here.**\n\n    payload = the structu"}],"package":null},"verification":{"claimed":false,"claimedAt":null,"proofs":[]},"provenance":{"sources":[{"source":"mcp_registry","key":"io.agent4/agent4-tenant","url":"https://registry.modelcontextprotocol.io/v0/servers/io.agent4%2Fagent4-tenant","firstSeenAt":"2026-09-05T23:21:00.599Z","fetchedAt":"2026-09-05T23:21:00.599Z","normalizedAt":"2026-09-05T23:21:00.599Z"}]},"firstSeenAt":"2026-09-05T23:21:00.599Z","updatedAt":"2026-09-06T02:28:32.423Z"}