From f84cbd1db5c69dd6c309f5e8fb206971ea65f655 Mon Sep 17 00:00:00 2001 From: kjgbot Date: Fri, 4 Sep 2026 22:45:44 +0200 Subject: [PATCH] docs(relayfile): hand the agent brief over as markdown, and separate provisioning from the mount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two problems with how the review-bot guide presented itself. The agent brief was a sidebar page. Its audience is an agent fetching the markdown mirror, not a human browsing docs, so a nav entry invited the wrong reading — that you go and read it. It is now unlisted: dropped from the sidebar, still built and indexed, and reached from a "Give your agent a guide for this" section at the end of the guide that hands over the one thing you actually do with it: curl -o AGENTS.md https://agentrelay.com/docs/file/markdown/review-bot-brief.md `ProductDocSection` gains `unlistedSlugs` for this: slugs that stay in getProductDocSlugs — which drives the page, og and markdown routes plus the search index — while staying out of the nav the sidebar renders. Step 1 conflated provisioning with the local mount. It read as "one command sets everything up, including a mount", so a reader building a cloud bot came away thinking the local mirror was load-bearing. It says now that `relayfile setup` is provisioning, done once by a human on a machine with a browser because the OAuth needs one; that the mirror it leaves is for inspecting the tree; and that a deployed bot mounts per run in step 5 or skips the mount entirely. It also explains why --local-dir is passed at all — --skip-mount still prompts (relayfile#461). Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01NVwyjaMnm1PTRC6m7oXHJV Session-Id: 13b5d5ea-39b6-42f3-86df-6d7bf3570e4b --- web/content/docs/file/review-bot-brief.mdx | 6 +++++- web/content/docs/file/review-bot.mdx | 21 +++++++++++++------ web/lib/product-docs-nav.ts | 20 +++++++++++++----- web/lib/test/product-docs.test.ts | 24 ++++++++++++++++------ 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/web/content/docs/file/review-bot-brief.mdx b/web/content/docs/file/review-bot-brief.mdx index 4d5460f..ef66d55 100644 --- a/web/content/docs/file/review-bot-brief.mdx +++ b/web/content/docs/file/review-bot-brief.mdx @@ -4,7 +4,11 @@ description: 'A complete, copy-paste operating document for a Relayfile-backed P --- - **This whole page is the brief.** Everything below is addressed to the agent, not to you. Take it with **Copy page as markdown** (top right) or `curl -o AGENTS.md https://agentrelay.com/docs/file/markdown/review-bot-brief.md`. + **This whole page is the brief.** Everything below is addressed to the agent, not to you — it is meant to be fetched as markdown and handed over, not browsed: + + ```bash + curl -o AGENTS.md https://agentrelay.com/docs/file/markdown/review-bot-brief.md + ``` Before handing it over, replace every `` placeholder — `/` and the specialist name are the two you set once, and ``, ``, ``, ``, ``, ``, and `` are filled per run or per finding. Verified against `relayfile` 0.10.53; it pairs with [Build a PR review bot](/docs/file/review-bot). diff --git a/web/content/docs/file/review-bot.mdx b/web/content/docs/file/review-bot.mdx index 1514113..266c96d 100644 --- a/web/content/docs/file/review-bot.mdx +++ b/web/content/docs/file/review-bot.mdx @@ -50,7 +50,7 @@ The integration stack is hosted either way — what changes is where the bot's p ## 1. Connect GitHub -One command logs you into Cloud, creates the workspace, runs the provider OAuth, waits for the first sync, and mounts the result: +One command logs you into Cloud, creates the workspace, runs the provider OAuth, and waits for the first sync. This is **provisioning** — a human does it once, on a machine with a browser, because the provider OAuth needs one: ```bash relayfile setup \ @@ -62,6 +62,8 @@ relayfile setup \ `--no-open` prints the login and connect URLs instead of launching a browser — always pass it when an agent (or CI) is driving the command, since a headless browser launch burns the OAuth state. +The local mirror it leaves behind is for *you*: somewhere to `ls`, `cat` and `grep` the tree and see exactly what your agents will see. It is not how a deployed bot reads the workspace — cloud sandboxes mount per run in [step 5](#5-give-every-sandbox-the-same-workspace), and short-lived functions skip the mount entirely. `--local-dir` is required here only because `--skip-mount` still prompts for a directory ([relayfile#461](https://github.com/AgentWorkforce/relayfile/pull/461)). + Both URLs are short-lived. A Cloud device code expires in minutes and the Nango connect URL has its own TTL, so complete them while the command is still waiting. If it exits first, re-run the same line — a re-run reuses the workspace and only opens a new connect flow when the provider isn't connected yet. @@ -413,6 +415,16 @@ Alternatives: subscribe in-process with the SDK (`connectWebSocket({ onEvent })` Either way the reviewer wakes on provider state changing rather than on a request arriving — see [Events and webhooks](/docs/file/events). In the cloud, keep the subscriber in one long-lived orchestrator that spawns a sandbox per PR. +## Give your agent a guide for this + +Everything above is written for you. The same contract written for the agent — its environment, the orient-before-acting rules, its ACL boundaries, the `/runs` run protocol, discovery-first writeback, and how to confirm a write actually landed — is one markdown file you can hand it directly: + +```bash +curl -o AGENTS.md https://agentrelay.com/docs/file/markdown/review-bot-brief.md +``` + +Drop it in as `AGENTS.md`, `CLAUDE.md`, or a skill. Replace the `` placeholders before handing it over: `/` and the specialist name are set once, while ``, ``, ``, ``, `` and `` are filled per run. + ## Tear down ```bash @@ -426,9 +438,6 @@ rm -rf ./relayfile-mount `relayfile workspace join --name ` **renames an existing local entry** for that workspace id rather than adding a second one. If you're scripting workspace setup, check `relayfile workspace list` before and after. - - Copy-paste agent brief — the same contract written for the agent itself, ready to drop in as `AGENTS.md`. - @@ -440,7 +449,7 @@ rm -rf ./relayfile-mount Why the orchestrator sees a specialist's write on the next read. - - The copy-paste operating document to hand the agent. + + Every flag used in this guide. diff --git a/web/lib/product-docs-nav.ts b/web/lib/product-docs-nav.ts index 79ad751..6758978 100644 --- a/web/lib/product-docs-nav.ts +++ b/web/lib/product-docs-nav.ts @@ -29,6 +29,12 @@ export interface ProductDocSection { repo: string; /** Current published version, shown as a badge in the sidebar header. */ version?: string; + /** + * Slugs that are built and indexed but deliberately kept out of the sidebar — + * pages whose real audience is an agent fetching the `.md` mirror, not a + * human browsing the nav. + */ + unlistedSlugs?: string[]; nav: NavGroup[]; } @@ -38,6 +44,8 @@ export const fileSection: ProductDocSection = { tagline: 'The event layer for AI agents.', repo: 'AgentWorkforce/relayfile', version: '0.10.53', + // Handed to an agent as markdown from the review-bot guide, not browsed. + unlistedSlugs: ['review-bot-brief'], nav: [ { title: 'Start', @@ -49,10 +57,7 @@ export const fileSection: ProductDocSection = { }, { title: 'Guides', - items: [ - { title: 'Build a PR review bot', slug: 'review-bot' }, - { title: 'Review bot agent brief', slug: 'review-bot-brief' }, - ], + items: [{ title: 'Build a PR review bot', slug: 'review-bot' }], }, { title: 'Concepts', @@ -221,7 +226,12 @@ export function getProductSectionForPath(pathname: string): ProductDocSection | } export function getProductDocSlugs(section: ProductDocSection): string[] { - return [...new Set(section.nav.flatMap((group) => group.items.map((item) => item.slug)))]; + return [ + ...new Set([ + ...section.nav.flatMap((group) => group.items.map((item) => item.slug)), + ...(section.unlistedSlugs ?? []), + ]), + ]; } export const productBasePath = (section: ProductDocSection): string => `/docs/${section.id}`; diff --git a/web/lib/test/product-docs.test.ts b/web/lib/test/product-docs.test.ts index 5502b09..ccaa63f 100644 --- a/web/lib/test/product-docs.test.ts +++ b/web/lib/test/product-docs.test.ts @@ -1,6 +1,11 @@ import { describe, expect, it } from 'vitest'; -import { factorySection, fileSection, getProductSearchIndex } from '../product-docs'; +import { + factorySection, + fileSection, + getProductDocSlugs, + getProductSearchIndex, +} from '../product-docs'; describe('Factory product docs', () => { it('publishes issue routing in navigation and scoped search', () => { @@ -24,13 +29,20 @@ describe('Factory product docs', () => { }); describe('Relayfile product docs', () => { - it('publishes both review-bot guides in a Guides group', () => { + it('lists only the human guide in the sidebar', () => { const guides = fileSection.nav.find((group) => group.title === 'Guides'); - expect(guides?.items).toEqual([ - { title: 'Build a PR review bot', slug: 'review-bot' }, - { title: 'Review bot agent brief', slug: 'review-bot-brief' }, - ]); + expect(guides?.items).toEqual([{ title: 'Build a PR review bot', slug: 'review-bot' }]); + }); + + it('still builds and indexes the agent brief, unlisted', () => { + const navSlugs = fileSection.nav.flatMap((group) => group.items.map((item) => item.slug)); + + expect(navSlugs).not.toContain('review-bot-brief'); + expect(fileSection.unlistedSlugs).toContain('review-bot-brief'); + // getProductDocSlugs drives the page, og and markdown routes, so the .md + // endpoint the guide links to must stay in it. + expect(getProductDocSlugs(fileSection)).toContain('review-bot-brief'); }); it('indexes the review-bot guide, including the cloud path', () => {