{"name":"AgentTrove","description":"AgentTrove — a folder and knowledge catalog exposed over MCP. Read folders and documents, create and organise knowledge, and chat with folder context, on behalf of the signed-in owner.","version":"0.1.0","provider":{"organization":"AgentTrove","url":"https://agenttrove.ai"},"documentationUrl":"https://app.agenttrove.ai/.well-known/agent-protocol","supportedInterfaces":[{"url":"https://app.agenttrove.ai/api/mcp/streamable-http","protocolBinding":"JSONRPC","protocolVersion":"2025-06-18"}],"capabilities":{"extensions":[{"uri":"https://modelcontextprotocol.io/specification/2025-06-18","required":true,"description":"This interface speaks MCP JSON-RPC (initialize, tools/list, tools/call), not A2A task methods.","params":{"transport":"streamable-http","discovery":"https://app.agenttrove.ai/.well-known/mcp.json"}}]},"securitySchemes":{"oauth2":{"oauth2SecurityScheme":{"description":"OAuth 2.1 authorization code with PKCE (S256). Dynamic client registration is supported.","oauth2MetadataUrl":"https://app.agenttrove.ai/.well-known/oauth-authorization-server","flows":{"authorizationCode":{"authorizationUrl":"https://app.agenttrove.ai/api/oauth/authorize","tokenUrl":"https://app.agenttrove.ai/api/oauth/token","scopes":{"folder:read":"Read folders, documents, context and grounding in the granted scope.","folder:write":"Create, update, move and archive documents and folders in the granted scope.","chat:append":"Append messages to a folder conversation.","agent:publish":"Publish and unpublish the agent website in the granted scope."},"pkceRequired":true}}}}},"securityRequirements":[{"schemes":{"oauth2":{"list":["folder:read"]}}}],"defaultInputModes":["application/json"],"defaultOutputModes":["application/json"],"skills":[{"id":"indy_action_send_followup","name":"Send a followup message on a request","description":"Send a followup message to the agent owner about a request you previously submitted with request_action. Use this to answer questions the owner asked, provide additional details, or negotiate terms (e.g. \"Yes, Tuesday at 2pm works\").\n\nThe owner will be notified and can reply. Poll action_status to see their response.\n\nEach side may send only a small number of follow-ups per thread; the tool refuses past that.","tags":["read"]},{"id":"indy_action_status","name":"Check a request you made to this agent","description":"Look up a request previously submitted with request_action — pass the request ID that call returned, or omit requestId to list the caller’s recent requests on this agent. Returns whether the owner has answered yet.\n\nThe response includes a followups array with any messages the owner has sent about this request. Use the since parameter to poll incrementally — pass the latest followupsSince value from the previous response to get only new messages.\n\nA pending request is not a held slot — say it is still awaiting the owner, never that it is booked. Do not read the request ID aloud in a voice conversation.","tags":["read","read-only"]},{"id":"indy_add_leaf","name":"Add leaf to folder","description":"Create a new leaf (page) under parentFolderId. parentFolderId must be the token folder or a descendant. Citations are required; every claim should be sourced. idempotencyKey must be a unique UUID per logical write.","tags":["write"]},{"id":"indy_agent_publish","name":"Publish agent","description":"Publish this folder’s agent publicly — the same ceremony as the console Publish button: health check, short-address assignment, billing-attribution check, live link. Requires agentPublishConsent: true (you are asserting the owner agrees to go public). The address is assigned automatically — never guessed.","tags":["write"]},{"id":"indy_append_chat","name":"Append message to folder chat","description":"Append a chat message to the folder thread. Use this to narrate progress, explain decisions, or post a summary at the end of a research session.","tags":["chat"]},{"id":"indy_approve_plan","name":"Approve grounding plan","description":"Approves a proposed grounding plan so brochure composition can proceed. Call this after indy.estimate_grounding_plan and after the user has reviewed and approved the plan. Once approved, call indy.compose_brochure with the planId.","tags":["write"]},{"id":"indy_archive_leaf","name":"Archive leaf","description":"Request approval to move a leaf to the folder's /archive sub-folder. Used when a leaf is stale or superseded. The leaf row is preserved (not deleted) so the user can un-archive.","tags":["write"]},{"id":"indy_ask_agent","name":"Ask this agent","description":"Ask the published agent a question and receive ITS answer — generated from the knowledge its owner published, under the owner's own rules. Use this when the question is about what this agent covers; the read tools are for inspecting the material yourself. One question per call, up to 2000 characters. The answer is the agent's and is attributed to it. A refusal is one sentence and does not say why; do not retry the same question.","tags":["read","read-only"]},{"id":"indy_build_site","name":"Build a publishable site pack","description":"Generate a static site (files + manifest) for this agent, or for a chosen set of one owner’s agents. The pack is NOT published — host it yourself at the domain you pass as `host`.\n\nTwo modes: pass `handle` for a single-agent site (omit it to build for the agent you are talking to), or pass `ownerSlug` + `selections` (the cardIds indy_list_owner_agents returned) for a multi-agent site. Each selection may carry `actionIds`; omit it for the agent’s featured defaults, pass [] to render the agent without forms.\n\nForms on the generated site submit to each agent’s own MCP endpoint, named in manifest.agents[].mcpEndpoint. If executable forms are not enabled for the owner, the same actions render as descriptive links only. Pass `embed: true` to also get per-agent chat embed snippets where the agent’s allowlist covers your host.","tags":["read","read-only"]},{"id":"indy_check_plan","name":"Check whether a plan is executable here","description":"Grades a list of suggested improvements against what this deployment can actually do. Each item comes back with your original wording and one of three verdicts: \"executable\" (you can do this now), \"blocked\" (with the specific reason — a toggle that is off, a migration that has not been applied, a tier ceiling, or a capability that is shipped but inert), or \"not-measurable\" (this grader has no way to check it, and claims nothing either way). Use it before acting on suggestions so you do not spend an afternoon on something that cannot work here.","tags":["read","read-only"]},{"id":"indy_cite_check","name":"Check citations against folder policy","description":"Validate citation URLs against the folder's allowDomains / blockDomains. Returns which URLs are allowed and which are blocked (with reason). Call this BEFORE add_leaf or update_leaf to avoid wasted writes. The server re-validates on write.","tags":["read","read-only"]},{"id":"indy_compose_brochure","name":"Compose brochure from grounding plan","description":"Composes a visual brochure (CanvasOps) from an approved grounding plan. Default path: call indy.estimate_grounding_plan + indy.approve_plan first and pass the planId here. Agent-native shortcut: pass autoApprove=true (and omit planId) to inline the estimate+approve step in this single call — recommended for autonomous agents like Perplexity Computer. Pass localizeAfter=[\"hi-IN\",\"te-IN\"] to chain indy.localize_brochure in the same call after a successful compose. The compose is resumable: if interrupted, calling again with the same planId will resume.","tags":["write"]},{"id":"indy_create_agent","name":"Create agent folder","description":"Create a NEW agent — a fresh root-level folder in the caller's catalog, optionally seeded with .agent config (agentFrontmatter: name, personality, greeting, purpose, rules) and a .context note (contextSeed, <=8KB). The folder is minted owned by the token's bound user; seeds are validated BEFORE creation and applied through the same create branch the Configure editor uses. NOTE: the new folder is OUTSIDE this token's folder scope — the result names its folderId, and the owner mints a fresh token bound to it to manage it further. Requires write on the catalog root. Owner-only.","tags":["write"]},{"id":"indy_create_subfolder","name":"Create sub-folder","description":"Create a sub-folder under parentFolderId. Sub-folders are 1 level deep max (parent must be the token folder). Use for grouping related leaves.","tags":["write"]},{"id":"indy_describe_agent","name":"Describe this agent","description":"Report this agent's current state — what it knows, who it has reached, and what is worth doing next. Owner-only, read-only. Returns structured facts; write the summary yourself rather than quoting it.","tags":["read","read-only"]},{"id":"indy_describe_card","name":"What this agent is and how to reach it","description":"Returns this agent's whole card in ONE call: who it is, its public links, what it covers and does not, the requests it accepts, and an overview of what it knows. Call first when a person asks about this agent itself or wants to reach its owner — cheaper than assembling the same answer from several reads.","tags":["read","read-only"]},{"id":"indy_describe_mcp_access","name":"Report what this connection may call","description":"Answers \"why can't I do X here\" — which registered tools this agent's mcp_allowed_tools list hides from tools/list and refuses at call, whether MCP is enabled, paused or cost-capped, and exactly how the owner widens access. Call this when a capability you expected is absent from the tool list before telling the owner it does not exist.","tags":["read","read-only"]},{"id":"indy_describe_templates","name":"Describe brochure templates","description":"Returns template descriptors showing what content structure each brochure layout expects (leaf count, titles, summaries, images, edges). When folderId is provided, also returns grounding analysis: current leaf/edge counts, auto-detected best template, and content gaps. Use this before populating leaves to ensure content matches the target layout.","tags":["read","read-only"]},{"id":"indy_direct_line_poll","name":"Poll for a Direct-Line answer","description":"Check whether the human expert has answered a previously submitted Direct-Line request. Pass the requestId handle returned by indy.direct_line_request.","tags":["read","read-only"]},{"id":"indy_direct_line_request","name":"Ask the human behind this agent","description":"Escalate a question to the human expert behind this agent when you cannot answer it from the agent's grounded knowledge (or when grounding was truncated / low-confidence). The human answers asynchronously; you receive a pending handle to poll, and the human also emails the asker directly. Use sparingly — there is a per-day limit.\n\nWhen calling this from a VOICE conversation:\n  1. SPEAK FIRST, TOOL SECOND. Before invoking this tool, say ONE short sentence in the caller's language acknowledging the escalation — e.g. \"Let me get you a human answer on that\" / \"एक इंसान इसका जवाब देंगे, थोड़ी देर में।\" / \"Deixa eu pedir a alguém que responda isso.\" Do NOT stay silent while the tool runs.\n  2. After the tool returns, tell the caller HOW they will get the answer — \"I'll email you within N hours\" — using slaHours from the tool response. Do NOT read the request ID aloud.\n  3. Pass callerLocale on the tool call so the human answer arrives in the caller's language. Use the language of the current conversation.","tags":["read"]},{"id":"indy_estimate_grounding_plan","name":"Estimate grounding plan","description":"Proposes a budgeted grounding plan across one or more folders. Returns per-folder FULL/COMPACT/SKIP allocations within the token budget. IMPORTANT: Present the plan to the user and wait for approval before reading any folder content. Do NOT call read_grounding or read_leaf until the user explicitly approves this plan.","tags":["read","read-only"]},{"id":"indy_export_package","name":"Export agent package","description":"Export the scoped folder as a portable .agentpkg file. Returns base64-encoded bytes and manifest metadata. Use this to download an agent for backup or transfer to another account.","tags":["read","read-only"]},{"id":"indy_get_workflow","name":"Read an agent workflow (draft graph)","description":"Read this account's agent workflows so you can propose an edit. Call with NO arguments first: it lists the workflows you can edit, each with a status and an updatedAt token. Then call again with { workflowId } to get the full DRAFT graph (nodes, edges, instructions), its validation diagnostics, and its updatedAt. Edit the graph and submit it with indy.update_workflow — the edit is saved as a draft; a human publishes it from the canvas. This tool never changes anything.","tags":["read","read-only"]},{"id":"indy_goal_turn","name":"Interpret a request-form answer","description":"Interpret ONE user message against one declared request action — the interpretation leg for agents collecting a request conversationally. Returns `{intent, ops}` where each op is a validated field write you may apply to your local fill; it never returns prose, and the caller decides what to say.\n\nUSE IT WHEN your interpretation stalls: the user answered a choice with an alias or in their own words, or a free-text answer might hide a correction or a question. Do NOT call it to submit — `indy.request_action` commits. `intent: \"question\"` means the user asked something; answer it yourself, the ops are empty. `intent: \"unknown\"` means nothing changed — keep your own reading.\n\nRate-limited per caller and per session; budgets apply. Only actions listed by indy_describe_card (or the no-args request_action call) are reachable; others refuse identically to a nonexistent one.","tags":["read"]},{"id":"indy_install_package","name":"Install agent package","description":"Install a reviewed .agentpkg into the target folder. Requires an approvedPlanDigest from plan_package_install. Idempotent via idempotencyKey.","tags":["write"]},{"id":"indy_list_owner_agents","name":"List one owner's distributable agents","description":"List the agents a given owner has cleared for external distribution — each with its public card id, MCP endpoint, page URL and a summary of the actions it offers.\n\nPass the ownerSlug from a card manifest (subject.ownerSlug or the @handle in the agent page URL); do not guess it from a display name. Results are paginated — pass the returned nextCursor to continue. An empty agents list means the owner has nothing publicly distributable right now; it does not confirm or deny that the owner exists. Eligibility can change between calls — re-check an agent’s own describe_card before submitting or building.","tags":["read","read-only"]},{"id":"indy_localize_brochure","name":"Localize brochure to target languages","description":"Translates the text bindings of a composed brochure canvas into target locales (e.g. hi-IN, te-IN). Images, video, and layout are preserved byte-identical. Requires a composed brochure — call indy.compose_brochure first.","tags":["write"]},{"id":"indy_move_node","name":"Move node","description":"Reparent a catalog node (leaf or subfolder) to a different parent folder. Used for folder reorganization. Rejects cycles and root-folder moves.","tags":["write"]},{"id":"indy_patch_leaf_section","name":"Patch leaf section","description":"Replace exactly one markdown section in a leaf by heading. Creates a pending Brainstormly diff approval; it does not directly mutate the document.","tags":["write"]},{"id":"indy_plan_package_install","name":"Plan agent package install","description":"Preview what installing an .agentpkg would do without making changes. Returns planned operations, blockers, and a planDigest to pass to install_package. Always call this before install_package.","tags":["write"]},{"id":"indy_publish_all","name":"Publish agent + website","description":"One-call publish: agent goes live (reuses the existing publication when one is already active) and the website publishes — embedded agent included when the site is in combined mode. Creates a freeform site from public context when none exists. All attestations are literal true; embedAcknowledged is required when the site embeds the agent. Partial failure is reported per leg — read the legs field.","tags":["write"]},{"id":"indy_read_agent","name":"Read folder .agent","description":"Read a folder's .agent configuration document — parsed frontmatter, body, and the `etag` (bodyVersion) `indy.update_agent` expects for optimistic locking. Returns `etag: 0` and empty fields when no .agent leaf exists yet; `parseError` when the stored markdown does not round-trip (a PATCH onto that base is refused — repair in the raw editor). Owner-only.","tags":["read","read-only"]},{"id":"indy_read_competitor_intel","name":"Read competitor intelligence","description":"Returns a competitor-intel view of the granted folder shaped as {us, competitors[]}. The first leaf is treated as \"us\" (the company being pitched). Subsequent leaves are treated as competitors. When includeRefresh=true, each competitor is enriched with deterministic Comet signals (pricing/product/hiring/news). Use BEFORE composing a battle-card brochure so the macro has the freshest positioning data.","tags":["read","read-only"]},{"id":"indy_read_context","name":"Read folder .context","description":"Read the Living Context (.context markdown + merged parent chain) for the folder this token is scoped to. Use this before deciding what to populate.","tags":["read","read-only"]},{"id":"indy_read_folder","name":"Read folder snapshot","description":"Read snapshot of the folder (leaves + subfolders + .context). The response includes the folder context with rules and constraints — always follow them before adding or updating leaves.","tags":["read","read-only"]},{"id":"indy_read_grounding","name":"Read folder grounding card","description":"Returns a grounding card for the granted folder. IMPORTANT: Always call with mode=\"estimate\" first. Present the estimate to the user and ask \"Read compact (~X tokens) or full (~Y tokens)?\" before proceeding. Do NOT skip the estimate step or choose a mode on behalf of the user. Modes: \"estimate\" returns a lightweight cost preview (leaf count, token estimates, edge count) without building the full card. \"compact\" returns a card with shorter summaries (~150 chars) for token-conscious reads. \"full\" returns the complete card with ~500-char summaries.","tags":["read","read-only"]},{"id":"indy_read_leaf","name":"Read leaf content","description":"Returns the content of a single leaf node. IMPORTANT: Always call with mode=\"compact\" first. If the response has truncated=true, tell the user how many total characters exist and ask \"Show full content (~N chars)?\" Do NOT call with mode=\"full\" unless the user explicitly asks for the complete body. Modes: \"compact\" (default) returns first ~500 chars as a preview. \"full\" returns the complete body.","tags":["read","read-only"]},{"id":"indy_remove_audience_rule","name":"Remove audience rule","description":"Remove a widget-owned audience policy for one leaf, tool, or action — the scope returns to ungoverned/inherited. scope=leaf: leafId; scope=tool: scopeId (agent:<toolId> or agent:inst:<slug>); scope=action: actionId (also lifts the .agent declaration). Rows owned by another writer (e.g. .context sync) are refused. Orphan rows stay removable. Idempotent when nothing is there. Requires manage on the folder; tool/action scopes need accessMatrix enabled. Owner-only.","tags":["write"]},{"id":"indy_remove_tool_instance","name":"Remove tool instance","description":"Remove one Visitor Action (tool instance) from a folder by slug. Refuses when no instance carries that slug. The remaining instances are written through the same validated whole-array core as the owner UI; expectedUpdatedAt is a CAS precondition (omit to CAS on the version this call reads). Requires agents enabled and manage on the folder. Owner-only.","tags":["write"]},{"id":"indy_request_action","name":"Make a request to the person behind this agent","description":"Submit a REQUEST — a viewing, a table, an application, an RSVP — to the person behind this agent, for them to accept or decline.\n\nCALL IT WITH NO ARGUMENTS FIRST. Each agent declares its own set of requests, and the schema below cannot list them, so the no-argument call returns exactly what this agent accepts and which fields each one needs. Then call again with an actionId from that list.\n\nWHAT THIS DOES NOT DO: it does not check availability, hold a slot, or confirm anything. Nothing here can see the owner's calendar or booking system. Tell the user their request has been SENT and is awaiting the owner — never that it is booked, reserved or confirmed. If the response comes back auto_approved, the owner set a standing rule in advance that this request matched; say that, and nothing stronger.","tags":["read"]},{"id":"indy_run_workflow","name":"Run an agent workflow","description":"Discover and run this account's published agent workflows. Call with NO arguments first: it returns the list of published workflows, each with an inputSchema describing exactly what the workflow expects. Then call again with { workflowId, inputs } to execute one. The run is synchronous and may take up to a few minutes; the response contains the workflow's named result slots, a runId, and the cost. Runs spend real money and are subject to a daily per-workflow cost ceiling.","tags":["write"]},{"id":"indy_set_audience_rule","name":"Set audience rule","description":"Set who can reach one leaf, platform tool, or action on a folder. scope=leaf: leafId + visibility (public/authenticated/owner_approved) + optional authPrompt; restating the inherited default converges to inherits unless exact=true. scope=tool: scopeId (agent:<toolId> or agent:inst:<slug>) + visibility (public/authenticated only). scope=action: actionId + visibility (public/authenticated only); also stamps the audience into .agent. expectedVisibility is a CAS precondition ('inherits' = no row). Tool/action scopes need accessMatrix enabled. Requires manage on the folder. Owner-only.","tags":["write"]},{"id":"indy_set_grounding_limits","name":"Set grounding limits","description":"Set a folder's grounding caps — maxLeaves (leaves read per answer) and/or tokenBudget. Values above the deployment ceiling are clamped and the response reports what was actually stored plus the effective ladder (saved → .context → default). Values below the floor are refused. Requires write on the folder. Owner-only.","tags":["write"]},{"id":"indy_update_agent","name":"Update folder .agent","description":"Patch a folder's .agent configuration — name, greeting, skills, refusals, actions, listing consent. Supply frontmatterPatch (shallow merge; null removes a key) and/or bodyPatch (full body replacement). expectedVersion is the etag from read_agent (0 = create a missing .agent); a mismatch returns 409 — call read_agent and retry. kycStatus is derived and refused. Runs the same validation and CAS guards as the Configure editor: AgentConfigSchema, the writable listing rungs, action-block lint, and the knowledge-tag/action-audience policy bridges. Requires context.write on the folder. Owner-only.","tags":["write"]},{"id":"indy_update_context","name":"Update folder .context","description":"Patch a folder .context document. Supply frontmatterPatch (shallow merge; undefined removes a key) and/or bodyPatch (full body replacement). expectedVersion is the etag from a prior read; mismatched versions return 409 so the caller can reload. Requires the context.write capability on nodeId. Metadata writes are not metered against the folder cost cap.","tags":["write"]},{"id":"indy_update_leaf","name":"Update leaf body","description":"Replace the body of an existing leaf. Skipped (no error) if the user has edited the leaf since the last agent write. Citations required.","tags":["write"]},{"id":"indy_update_workflow","name":"Edit an agent workflow (saves a draft)","description":"Propose an edit to one of this account's agent workflows. First read it with indy.get_workflow, edit the returned `graph`, then call this with { workflowId, graph, expectedUpdatedAt } (the updatedAt from get_workflow). The edit is validated, screened for prompt injection, and authorized against every agent folder it binds, then saved as a DRAFT. It does NOT go live: a human reviews and publishes it from the canvas. The response returns a diff of what changed and a canvas URL to review it.","tags":["write"]},{"id":"indy_upload_leaf_media","name":"Upload media to leaf","description":"Upload an image or video to a leaf. The file is stored in R2 and a structured reference is written to the leaf body. Images are appended as markdown image syntax, videos as links. Supported types: image/png, image/jpeg, image/webp, image/gif, image/svg+xml, video/mp4, video/webm, video/quicktime, video/x-msvideo. Images max 5 MB, videos max 50 MB. Base64-encoded data required.","tags":["write"]},{"id":"indy_upload_leaf_media_from_url","name":"Upload media to leaf from URL","description":"Fetch an image or video from a URL and upload it to a leaf. The server fetches the media, stores it in R2, and writes a structured reference to the leaf body. Preferred over upload_leaf_media when the caller has a URL instead of base64 data. Supported types: image/png, image/jpeg, image/webp, image/gif, image/svg+xml, video/mp4, video/webm, video/quicktime, video/x-msvideo. Max fetch size: 5 MB. 10-second timeout.","tags":["write"]},{"id":"indy_upsert_tool_instance","name":"Upsert tool instance","description":"Add or replace one Visitor Action (tool instance) on a folder — matched by slug. Instanceable kinds are book_slot, decision_card, remind_me and start_playbook; start_workflow binds are normally created by the workflow publish surface — an enabled bind is still gated here to a published workflow that names this folder. The instance is validated and written through the same core as the owner UI: every enabled kindId lands on the tools allowlist, and capability-off enabled kinds are stored but reported in warnings. expectedUpdatedAt is a CAS precondition; omit it to CAS on the version this call reads. Requires agents enabled and manage on the folder. Owner-only.","tags":["write"]},{"id":"indy_verify_email","name":"Verify your email","description":"Verify the user's email address via a one-time code. Call TWICE:\n\n1. First call: `{email}` — sends a 6-digit code to the email address.\n2. Second call: `{email, code}` — verifies the code and returns an authProof token. Pass this token as `authProof` to indy_request_action to access actions that require email verification.\n\nAsk the user for their email first, then for the code they received. The code expires in 10 minutes. If the code is wrong, they can retry. If expired, call again with just the email to get a new code.","tags":["read"]},{"id":"indy_website_create","name":"Create or adopt website draft","description":"Create this folder’s website draft (or return the existing one — one site per folder, `adopted: true`). `template` defaults to `freeform`, which auto-selects every currently public leaf plus the agent’s own context as the intro. `mode` is `website_only` or `website_with_agent` (embeds the live agent chat — requires the agent to be published, e.g. via indy.agent_publish, before the site can go live). Follow with indy.website_sources → indy.website_update → indy.website_publish.","tags":["write"]},{"id":"indy_website_get","name":"Get website state","description":"Read this folder’s website: status, draft selection and presentation, the consent/CAS versions (`draftVersion`, `stateVersion`, `consentGeneration`) every write needs, and the live URL once published. Returns `state: null` when no site exists yet — create one with indy.website_create.","tags":["read","read-only"]},{"id":"indy_website_publish","name":"Publish website","description":"Publish the draft website. All three attestations must be literal true — you are asserting the owner reviewed the facts, holds the rights, and accepts the content is public. For a site created with embed (website_with_agent) also set attestations.embedAcknowledged and publish the agent first (indy.agent_publish). expectedStateVersion is the CAS from indy.website_get.","tags":["write"]},{"id":"indy_website_sources","name":"List publishable website sources","description":"List every leaf under this agent’s folder with its live publish eligibility (`ok`/`code`, `inboxPending`, `contextIdentity`), plus the site template’s slot contract (`slots[].key/max/identity`). Use the eligible leaf ids in indy.website_update `selection`; on the freeform template, the `contextIdentity` row may go ONLY in the `identity` slot.","tags":["read","read-only"]},{"id":"indy_website_unpublish","name":"Unpublish website (and agent)","description":"Take the website down immediately: `target: \"website\"` un-publishes the site only (the draft and address are kept — republish later); `target: \"site_and_agent\"` also revokes the embedded agent publication the site is bound to. `expectedStateVersion` is the CAS from indy.website_get. This is a withdrawal — it works even while the folder is paused or over its cost cap.","tags":["write"]},{"id":"indy_website_update","name":"Update website draft","description":"Save the website draft: `selection` maps slot keys (from indy.website_sources) to ordered leaf ids — `identity` is the intro, `sections` renders one section per leaf in array order. `sectionOrder` reorders the existing sections (exact permutation). `presentation` carries siteTitle/sectionTitles/hiddenSections/siteLanguage for the freeform template. `expectedDraftVersion` is the CAS from indy.website_get. To publish, also pass `deriveDisclosures: true` + `noOtherRestrictedDisclosureConfirmed: true` — the disclosure attestation lives here, not on publish.","tags":["write"]}],"signatures":[{"protected":"eyJhbGciOiJFZERTQSIsImtpZCI6Ijg3MWMwMGQ4OTU5ODEwZjQiLCJ0eXAiOiJKT1NFIiwiamt1IjoiaHR0cHM6Ly9hcHAuYWdlbnR0cm92ZS5haS8ud2VsbC1rbm93bi9hZ2VudC1qd2tzLmpzb24ifQ","signature":"i8SIB4eePdKrDvyXNJEwD7o1g07nIzZ1zSzYE1FiMYjppGod_XA4DzT8ibmI_wRwbf-ns-XfXLQA9KlIHxA9AQ"}]}