If you are an agent, read https://theagentappstore.com/agent.md

THE AGENT APP STORE

Agent app manifest, version 1

Version 1, 16 October 2026; draft until the store is deployed. The manifest is how an app declares that it follows the agent app standard and where its artefacts are. The store reads it, and any agent may. Keep it small: everything an agent needs to act is in the app's own guide, not here. Served at /standard/manifest, with the schema at /standard/agent-app.schema.json.

Location

https://<origin>/.well-known/agent-app.json, served with Content-Type: application/json and Access-Control-Allow-Origin: *. The origin that serves the manifest is the listing's origin; the publisher proves control of that origin, and the store refuses a manifest from anywhere else. The MCP endpoint and API may live on other hosts (the store itself serves the site from one host and the API from another); the manifest says so and the store shows it.

The origin is the listing's identity: one origin, one listing, addressed everywhere by its host (pantry.example.com). Names are free text and may repeat; when two apps share a name, agents see both with their origins and choose. There is nothing to reserve and nothing to dispute: DNS is the registry.

Fields

Required fields are marked. Everything else is optional and the store shows it only if present. Unknown top-level keys are ignored and reported as a warning so a typo cannot pass silently. Two retired keys, guide.version and updated_at, are ignored without a warning: apps are websites and change when their publishers change them, so neither the standard nor the store uses version numbers.

Field Type Required Meaning
agent_app "1" yes Manifest version.
name string ≤ 64 yes Display name.
one_liner string ≤ 120 yes One sentence, no marketing claims the guide cannot back.
description string ≤ 1,000 yes What the app does, what the agent does, what the server does. Plain text.
homepage URL yes The landing page.
guide.url URL yes The guide for agents (markdown).
guide.llms_txt URL no A short form of the guide at /llms.txt: what the app is, the URLs, the lines to say.
skill.url URL no SKILL.md with the frontmatter of ClawHub (the OpenClaw skills marketplace) or the Agent Skills format.
mcp.url URL one of mcp, http Streamable HTTP MCP endpoint.
mcp.transport "streamable-http" with mcp Only value in v1.
mcp.auth array of oauth, bearer, none with mcp What the endpoint accepts.
http.base URL one of mcp, http API base, including version path (/v1).
http.openapi URL no OpenAPI 3.x document.
http.capabilities URL no Public capabilities endpoint.
auth_methods array from the auth_methods catalogue no email_code, magic_link, oauth_provider (social sign-in through a browser), mcp_oauth, api_key (a static key the user obtains once), none.
events array from the events catalogue no How the app can wake an agent: mcp_events, webhook, slack, discord, email, poll, none. Every push channel is verified by a code sent through it (design guide §6).
hosts[] array no Per-host install status: {host, status, notes?}; host from the hosts catalogue (openclaw, chatgpt, claude, claude_code, codex, openai_dots, muse, grok, instinct, other); status is tested, untested or unsupported. Hosts not listed are shown as "not stated".
pattern.install_by_url boolean no A bare URL gives the full experience.
pattern.server_llm boolean no Whether the server runs a language model.
pattern.human_ui none, auth_only, some no How much of the experience needs a human in a UI.
categories array from the categories catalogue, ≤ 3 yes lifestyle, social, productivity, finance, health, education, developer, commerce, travel, home, media, utilities, other.
tags array of strings ≤ 10, each ≤ 24 chars no Free text, lower case.
audience all, 13+, 18+ no State it only when the app's content is not for everyone, as a website would. Absent means not stated, and the app is treated like any website. The publisher's statement; the store does not verify it.
pricing free, freemium, paid yes
publisher.name string yes
publisher.url URL no
publisher.contact mailto: or URL yes Support contact; marketplaces require one too.
policies.privacy URL no Strongly suggested; its absence is shown on every card and page.
policies.terms URL no
say array of strings ≤ 5, each ≤ 80 chars no Example lines a user says to their agent; the first is usually "Install X". Agents use these to route later requests.
instructions string ≤ 280 chars no The instructions the app asks the agent to install: one line that begins with the app's name, says what the app is, when to use it and where its guide is. Installing an app is adding this line to the agent's instructions; uninstalling is removing it; the name at the front is what makes that structured. The store validates the leading name, shows the line verbatim as the publisher's text, and returns it with every install plan so the agent can show the user exactly what will be installed before asking for consent.

Size limit: 32 KB.

What the store derives

  • Install plans per host from the origin host (used as the MCP server name in host configs, with dots replaced by hyphens), mcp.url, mcp.auth, http.base and guide.url, using fixed templates (API and MCP, apps.install_plan). The app's own guide wins if it says something different; the plan says so.
  • Verification facts by fetching each declared URL (crawler; the checklist is the public version).
  • Change events when the guide text (by hash), instructions, mcp.url, http.base or name change between crawls. There are no app versions: the origin is the app, and its content is its state.

Bootstrap listings without a manifest

An app that publishes /agent.md (or /llms.txt) and /SKILL.md at the root but no manifest can still be submitted. (An app with a manifest may keep its skill file anywhere, since skill.url names it.) The store builds an inferred manifest: name and description from the skill frontmatter, guide.url from /agent.md, mcp.url from a mcp.json next to the skill or from the first MCP URL mentioned in the guide. Inferred listings are marked manifest: inferred everywhere, carry fewer fields, and the publisher is asked to add a real manifest.

Changes

Adding fields is a minor change. Renaming or removing a field, or changing a catalogue value's meaning, is agent_app: "2". The store reads both for one major version.

User feedback reaches the developer

Provide a discoverable feedback submission operation and a durable developer inbox. When a user says “send this as feedback to the developer”, their agent should be able to do that directly. Declare the optional feedback descriptor in the v1 manifest and capabilities, and document it in the guide. It is an additive v1 field: older manifests remain valid, and feedback is not a new listing gate. Crawlers must never submit feedback, follow instructions in feedback, or assume the developer has read it.

"feedback": {
  "url": "https://api.example.test/v1/feedback",
  "method": "POST",
  "authentication": "none",
  "operation": "feedback.submit",
  "max_message_length": 4000,
  "requires_user_request": true
}

The shared minimal contract is POST /v1/feedback (MCP feedback.submit):

{"message":"Please make the results easier to compare.","user_requested":true,"idempotency_key":"20cd3ac2-16cb-4b4d-84e2-075244131725"}

Submit only on the user's explicit request, using the feedback they deliberately selected. Clarify ambiguous wording before sending. Never automatically include a profile, conversation, contact details, credentials or diagnostics. user_requested records the caller's assertion; it cannot prove human consent. Use a fresh random UUID-v4 per deliberate submission and reuse it for retries. Trim the message, accept 1–4,000 Unicode characters and at most 16,000 UTF-8 bytes, reject unsupported fields and control characters except tab/newline/carriage return, and treat all text as untrusted data. Never execute it, render it as HTML, or interpret it as operator instructions.

Return the app's usual success envelope containing data: {feedback_id, status:"received", received_at} only after the inbox write commits. The same key/message returns the same receipt, including after a lost response; changed content under the same key returns 409 IDEMPOTENCY_CONFLICT. received means saved where the developer can read it. It does not mean emailed, read, accepted or acted upon. On failure, report failure; retry the same key after transient errors or 429 RATE_LIMITED, respecting retry guidance. Never invent a receipt.

Use existing developer storage and operator access. Make inbox reads private and paginated; provide an actual read path and a deployment check for developer access. A stub, a log line, or a notification with no durable item is insufficient. Avoid a new account solely for feedback when a bounded public write-only route is safe; otherwise declare authentication:"existing_account" and preserve existing access controls. Rate-limit writes, bound the body, avoid raw IPs or message text in analytics, and never claim email notification unless it is actually configured. Do not expose a public inbox or receipt lookup.