Publish a door
This guide is for the company. People already send their agents to your website to compare, shop, book, and check on accounts. A door lets those agents ask your agent and get your answer, with a link to the product, plan, or booking page on your site. Your tools, keys, and records stay with you.
- 1Pick what answers
The agent on your chat page, your search, or the server package
- 2Serve the endpoints
POST /cap/v1/messagesandGET /cap/v1/messages/{id} - 3Publish agent.txt
One file at the site root, and a link from the homepage
- 4Check it
The checker reads the file and asks one public question
- 5Add the badge
An "Agents welcome" badge and one line in your footer
Copies a short prompt with links to the spec and the reference server. Paste it into Claude, ChatGPT, Cursor, or any coding assistant open in your project. The same prompt is at /implement.txt.
Show the prompt
Implement the Concierge Agent Protocol (CAP) in this project, so other people's AI agents can ask our agent questions and get answers, instead of scraping our site. They never get our tools, keys, or data.
Read these first:
- Spec: https://conciergeprotocol.org/spec
- Usage, with request and response examples: https://conciergeprotocol.org/usage
- Reference server and examples: https://github.com/conciergeprotocol/cap
Then:
1. Find how this project can answer a question today: its content, search, database, or an existing AI agent. Tell me what you found and where CAP's answer should come from. Ask before you choose.
2. Serve POST /cap/v1/messages and GET /cap/v1/messages/{id}, as the spec describes. Every request carries CAP-Version: 1.0 and CAP-From: agent:{id}. Return 400 when either is missing. Use this project's own framework, or install @conciergeprotocol/server and pass an answer function. If this project has no bot yet, @conciergeprotocol/agent builds that function from a model, an llms.txt file, and MCP tools. Both packages need Node.js 22. The reference server in https://github.com/conciergeprotocol/cap is the same server, and the one the spec is checked against.
3. Publish /agent.txt at the site root:
Protocol: CAP/1.0
Name: {our agent's name}
Chat: {a page where a person can chat with it}
CAP: https://{our domain}/cap/v1
Add <link rel="agent" href="https://{our domain}/agent.txt"> to the homepage <head> even when the root file is valid. Add one line to llms.txt that points at /agent.txt. If this host cannot serve a file at the root, redirect /agent.txt to the file. Callers try /agent.txt first and use the homepage link only when that file is not a door.
4. Keep secrets out. A reply never includes API keys, tools, prompts, or another person's data, and agent.txt lists none of them.
5. If people have accounts here and should ask about them, add login by following https://conciergeprotocol.org/login. Otherwise skip this step.
6. Test with curl: fetch /agent.txt, send a message, and read it back. Show me the responses.
7. After the door is live and passes https://conciergeprotocol.org/check, add the "Agents welcome" badge and its one line of text to the site footer, as https://conciergeprotocol.org/publish#5-add-the-badge describes. Pick the brand, light, or dark badge to suit the footer. Keep the line visible, never hidden from people.
Keep the change small, and match this project's existing code style.What a door does for you
Without a door, a visiting agent reads pages built for people. It renders scripts, gets past banners, and pieces together an answer. If it gets that far, the person still has to open your site and find the page again. Each of those is a place the person can drop off. You never see the question.
With a door, the path is shorter:
- Your answer, not an inference. Your agent answers from your catalog, docs, and policies. When a page and the record disagree, the visitor gets the record.
- The reply carries the link. Links go in the reply text: the product in the right size, the plan, the booking page, the order. The person's agent hands the link over, and the step happens on your site.
- No form to wait on. A pricing, stock, or policy question is answered when it is asked, not after a contact form and a callback.
- You see the questions. Every message is a question from someone deciding what to do next. Pages served to a crawler tell you none of that.
- A door you opened on purpose. Agents use the door you published instead of scraping your pages.
CAP-Fromnames the caller, but it is a label, not proof. Rate limits handle abuse, and OAuth tokens authenticate the person. - Only what the request may see. The visiting agent never gets your tools, prompts, or keys. A public question gets a public answer. An account answer carries that one person's details, and only with a token they granted.
The tradeoffs are plain. Each answer is a model call you pay for, so set a daily limit. The reply is only as good as your record, and your agent has to say "not available" when the record finds nothing. When every answer is already on a few accurate pages, a door adds little. When to publish an agent has the full test.
1. Pick what answers
The door is a way in. Behind it, use whatever already knows the answers:
- The agent on your chat page. A person on the chat page and an agent at the door reach the same agent. This is the usual case.
- Your own search or API. Answer from a function that searches your catalog or CMS.
- The server package.
@conciergeprotocol/serverspeaks/cap/v1. You pass ananswerfunction.@conciergeprotocol/agentbuilds that function from a model, anllms.txtfile, and MCP tools. See Run a server. - The reference server. The same process, in this repository, with a fixed reply, an echo, or a POST to a URL you run. The spec is checked against it.
A hosted agent works too. The chat page and the CAP URL can live on another host, because callers trust your domain, not the server.
2. Serve the endpoints
POST /cap/v1/messages { "message": "...", "context": { ... }, "previous_message_id": "..." }
GET /cap/v1/messages/{id}
CAP-Version: 1.0
CAP-From: agent:your-agent-idRequire CAP-Version: 1.0 and CAP-From: agent:{id} on every request, and return 400 when either is missing. Return 200 with the reply when it is ready, and 202 with Location and Retry-After when it is not. Keep the thread on your side, so a follow-up sends only the new question. Usage has request and response examples. The spec is the contract.
Write replies a person can act on:
- End with a link to the right product, plan, booking, or order page, as a plain URL in the text.
- Say "not available" when your records find nothing. Never fill the gap with a guess.
- Keep keys, tool names, prompts, and internal ids out of the reply.
Decide per question
A crawler shows you which page it took. A door shows you why the agent came, because every visit arrives as a question. Your agent can act on that before any tool runs:
- Answer a buyer's question, with a link to the right product, plan, or booking page.
- Route a high-value or high-touch request to a person: "Tables for 8 are booked with our team. Message us on WhatsApp at https://wa.me/...", with the party size and date in the link if you can.
- Decline a question you would rather not answer, such as a request for every price you have ever quoted. Reply
donewith a short, polite answer and a way to reach you. A refusal is not an error, so do not returnfailed.
Intent is what the caller says, not proof of who it is. Keep data you would not hand a competitor out of public answers entirely, and use rate limits and OAuth for the hard limits.
The Next.js example is a door as a route in an app. The store example runs a product question, a login, and an order question on one agent.
3. Publish agent.txt
Protocol: CAP/1.0
Name: Harbor Goods
Chat: https://harborgoods.example/chat
CAP: https://harborgoods.example/cap/v1
Spec: https://conciergeprotocol.org/cap.txtServe it at https://{domain}/agent.txt. Add the homepage link even when the root file is valid, because agents that are reading the page follow it:
<link rel="agent" href="https://harborgoods.example/agent.txt">Add one line to llms.txt that points at /agent.txt. If your host cannot serve a file at the root, redirect /agent.txt to the file. agent.txt explains each line.
4. Check it
The checker reads your agent.txt, sends one public question, and reports what passed. Fix the failed rows and run it again.
Then ask your own door the questions your customers ask, from an assistant with the CAP MCP server. Read the replies the way a buyer would: is the answer right, and does it end in a link to the right page?
5. Add the badge
badge.svgbadge-light.svgbadge-dark.svgOnce the checker passes, put the badge and one line of text in your footer. People see that your site answers agents. An agent reading the page finds your door without guessing. The badge links to the checker for your domain, so anyone can confirm the door works. The checker prints this snippet with your domain filled in when it passes.
Use the brand badge on most footers. Use the light one on cream, colored, or busy footers, and the dark one on navy or black footers. Change the file name in the snippet to switch.
<p class="cap-badge">
<a href="https://conciergeprotocol.org/check?domain=harborgoods.example"><img src="https://conciergeprotocol.org/badge.svg" width="140" height="20" alt="Agents welcome: this site answers AI agents through CAP"></a>
AI agents: this site supports the Concierge Agent Protocol. Ask our agent at <a href="https://harborgoods.example/agent.txt">https://harborgoods.example/agent.txt</a>.
</p>Keep the line visible. Text hidden from people and shown to agents reads as prompt injection to agent browsers, and as cloaking to search engines. A visible line reaches both, because agents read visible text too. Word it as a fact about your site, not an instruction to the agent. The homepage <link rel="agent"> from step 3 does the same job in the markup.
Add account questions
When people have accounts and should ask about them, add an OAuth line and follow Add login to your agent. Until then, account questions end in login_required, and the door answers public questions only.
CAP