Repository navigation
An agent connected to a remote brain can now save a stack of long pages in under a minute, and gbrain tells it how.
Agents writing to a brain over MCP (for example through gbrain serve --http on another machine) used to save pages one at a time, and each page cost several seconds of back-and-forth with the database. A large page also outlasted the reply's built-in wait, so the agent got "still pending" and had to keep asking. Writing 27 long research pages took about 15 minutes, followed by around 30 more calls to wire up links the pages already contained.
Now the agent sends its pages in batches with put_pages, waits for the commit in the same reply with wait_ms, and the server links [[wikilinks]] between the pages by itself. The server also does far less database work per page and publishes a whole batch in one transaction. The instructions every MCP agent receives at connect time say all of this up front.
Measured with 25 pages of 60 KB each, written over MCP to a Postgres brain 30 ms away (round trip), with embeddings and Git on:
| Before | Now | |
|---|---|---|
25 pages, one put_page at a time, with polling |
nearly 5 minutes (about 11 s a page) | not needed |
25 pages, 4 put_pages calls sent one after another |
not available | 49 s, no polling |
One 60 KB put_page |
7.2 s reply saying "pending", then polls (about 11 s total) | committed in about 6 s, in the reply |
| SQL statements on one page's publish path | 135 | 115 |
| Backlinks between the pages you just wrote | about 30 manual add_link calls |
built automatically after the commit |
To take advantage of v0.60.64.0
gbrain upgrade should do this automatically. Remote agents pick up the new instructions the next time they connect.
- Tell your agent (or let the connect-time instructions do it): "When you save more than three pages to gbrain, use put_pages with one request_id per batch and wait_ms 25000."
- Turn mention links off if you don't want them:
gbrain config set mcp.remote_auto_links false. - Verify:
gbrain call put_pages '{"request_id":"<uuid>","pages":[{"slug":"notes/test-a","content":"# A"},{"slug":"notes/test-b","content":"# B\n\nSee [[notes/test-a]]."}],"wait_ms":25000}'returns"state": "committed", andgbrain call get_links '{"slug":"notes/test-b"}'shows thementionslink tonotes/test-a.
Itemized changes
Batch writes
- New MCP tool
put_pages(full surface): 1-50 complete pages, 8 MB of content at most, per call. Every page is an ordinaryput_pagewrite with the same fences, revision checks and receipts. The pages are accepted together, so queue capacity (request count and bytes) is reserved for the whole batch, or the call refuses withqueue_capacityand accepts none. - One receipt per batch: the state of each page with its revision or its own error envelope, totals,
links, andnext(done,pollorfix_pages). A page refused for its own reason does not stop the others. A grant that cannot write refuses the whole call with onepermission_denied. - Replaying the identical call with the same
request_idnever writes twice.put_pageswith onlyrequest_idreports progress without resending content. A replay with different pages refuses withidempotency_conflictand names the changed pages. - Every page needs
put_pagepermission; bound clients get each page's slug fenced likeput_page.
Waiting for the commit
put_pageandput_pagesacceptwait_ms(0-30000, counted from arrival; default 5000 forput_page, 25000 forput_pages). It is not part of the write's identity, so a replay with a different wait is still the same write. Out-of-range values refuse withinvalid_write_waitbefore anything is accepted.- A pending receipt's
retry_after_mscomes from the server's recent publishing pace instead of a fixed 1 s. get_write_requeststates its poll cadence and final states; a pendingput_pagenameswait_msandput_pages.
Faster publishing
- A
put_pagesbatch publishes up to 8 pages per database transaction, with file-safe recovery: if one page fails, the group rolls back, every file is restored, and the pages publish one at a time so each failure stays with its own page. - Fewer database round trips per write: claiming, admission, recovery records and completion each take fewer statements, a page's own writes skip repeated reads, and a batch's shared admission reads run once.
- Connector writes wait for a pending withdrawal rewrite of the same page before reading its file, so a sync right after a
forgetno longer fails withsource_changed.
Links for remote writes
- Remote
put_page,put_pages,captureandedit_pagewrites queue alinkseffect after the commit. It turns[[wikilinks]]and markdown links in the page body into plainmentionslinks to pages that already exist in the same source, are visible to the writer and sit inside its slug grant. Typed, frontmatter and timeline edges stay off for untrusted writes. A batch links its pages to each other once its last page commits. - On by default;
mcp.remote_auto_links falseturns it off. Receipts reportauto_links.mention_linksand the effect'sadded/removedcounts.
Agent guidance
- The connect-time instructions put the prompt-critical lines first, so harnesses that read only the first 2,048 characters still see them:
context_packat session start,put_pagereplaces the whole page, and the writing guidance (put_pages,wait_ms, followingnext). put_page,add_linkandadd_timeline_entrydescriptions say when links and timeline entries come from the page itself.- The simple HTTP transport's 413 reply tells the agent to split the request and names
GBRAIN_HTTP_MAX_BODY_BYTES.
For contributors
- New e2e coverage: Postgres statement budgets per write phase, two-connection page-guard tests, grouped
put_pagepublication (happy path and per-member failure), and the remote links effect on both engines. - The initialize-instructions and served-schema budgets grew for the write guidance; a new test pins the prompt-critical lines inside the first 2,048 characters.