Skip to the document

Building with an AI agent

An AI coding agent can do everything in Writing a block, because a vault is plain files and every plicine command can answer in JSON. This page covers briefing an agent from a terminal, the three tools Plicine gives an agent running inside the app, and the AGENTS.md file that gives a terminal agent the same briefing. Working with an AI agent covers the palette itself.

What an agent can already do

A vault is plain files, so an agent reads documents and BLOCK.md files the same way it reads any other text file in a repository, no API needed. From there, the same commands covered in Writing a block work identically for an agent as for a person at a terminal:

  • plicine create-block <name> --scope <@org> --description "..." scaffolds a new block's manifest.json, package.json, BLOCK.md and src/index.tsx, giving the agent a consistent structure to fill in rather than a blank file.

  • plicine validate <dir> --json checks a block folder, compiling it, running its BLOCK.md examples through its schema, and rendering both Interactive and Print, and reports the result as JSON an agent can parse directly:

    {
      "ok": false,
      "summary": "Checked @acme/status-note@0.1.0 (5caad1f9782d), 1 example",
      "problems": [
        {
          "file": "status-note/BLOCK.md",
          "line": 18,
          "severity": "error",
          "message": "example: tone: Invalid option: expected one of \"info\"|\"success\"|\"warning\""
        }
      ]
    }
    

    Each entry in problems names the file, the line where it happened when known, whether it's an error or a warning, and a human-readable message, enough to locate and fix the problem without re-running anything exploratory first.

  • plicine pack <dir> --into <vault> builds the .block file and writes it into the vault's .vault/blocks/ folder, exactly as described in Writing a block.

The same applies to fixing or extending a block that's already installed: plicine block checkout <name> <vault> --json gives an agent the exact folder to work in (its dir field) without it having to guess where app data lives or unzip anything itself, and plicine block push --dir <dir> --json writes the result back, running the same checks validate does first and refusing ("ok": false) rather than writing anything broken. --create on checkout scaffolds a new block instead of failing when the name doesn't exist yet, so "add a block that does X" and "fix the pricing block" are the same loop with one flag different. See Editing an installed block and the CLI reference for the rest of the subcommands (edit, status, diff, discard), all with --json.

Why BLOCK.md's examples matter more than its prose

validate doesn't just check that a block compiles, it runs every fenced example in BLOCK.md through the schema and both renders, so a block with well-chosen examples gets a genuine, repeatable correctness check for free. This cuts both ways for an agent: examples are also the fastest way for an agent (or the person reviewing its work) to understand a block's shape without reading the schema line by line, which is exactly why pack warns when a BLOCK.md has no example fence at all, "agents rely on it as a few-shot sample". Keep an agent's brief focused on getting the examples right, varied inputs, at least one edge case, and the rest tends to follow.

A suggested loop

A workable pattern for briefing an agent to build a block:

  1. Describe the block in plain terms: what it shows, its fields with their types and defaults, and one or two concrete example prop sets, the same shape as a BLOCK.md "Fields" table.
  2. Scaffold it with create-block, then have the agent fill in schema, Interactive and Print in src/index.tsx, and replace the scaffolded example in BLOCK.md with real ones matching the brief.
  3. Run validate --json and feed any problems straight back to the agent to fix, repeating until "ok": true.
  4. pack --into the target vault.
  5. Remember that packing isn't the same as running: the first time the packed block appears in a document, a person still has to approve it (in the app, or with plicine trust --approve) before it renders anywhere, see Why a block asks before it runs. An agent's brief should say this plainly, so "the block is packed" doesn't get reported as "the block is live".

Which agents the app can host

The palette finds these if they're installed, looking at PATH the way your terminal sees it:

Agent What Plicine runs
Claude Code claude-agent-acp, or npx -y @agentclientprotocol/claude-agent-acp
Kiro kiro-cli acp
Gemini CLI gemini --experimental-acp
Codex codex-acp, or npx -y @zed-industries/codex-acp

Sign in with the agent's own command first. The Claude Code and Codex entries fall back to npx -y, which downloads the adapter from npm the first time and runs whatever version npm serves; install claude-agent-acp or codex-acp yourself to choose the version. Any other agent that speaks the Agent Client Protocol can go in agents.json in the app data folder (App data), and Add an agent in the palette's agent menu shows where that file is.

The first message of a conversation carries a primer about the vault: how documents and block fences work, how {{placeholders}} and templates work and which keys the vault's values set, the props of every built-in block, each block package with its BLOCK.md and whether you've approved it, how a block's code is drawn and what its sandbox rules out, the plicine commands for checking documents, filling templates and working on blocks, and which files not to edit by hand. It tells the agent that approving blocks is up to you.

Plicine's own tools

An agent in the palette gets three tools from Plicine itself, on top of its own file and shell tools. They exist because some things an agent needs are cheaper to ask the running app for than to work out from files: whether a document still checks out, what it looks like once it's laid out for print, and getting an edited block back into the vault.

Tool What you or your agent gets
validate_doc The same JSON as plicine validate --json, for one document or the whole vault: ok, a summary, and a problems list naming the file, the line, whether it's an error or a warning, and what's wrong
render_preview PNG images of the document's pages, rendered the way the PDF is. Up to four pages a call, or the pages you name
pack_block Checks a block checkout, packs it and writes it into the vault's .vault/blocks/, exactly as plicine block push does, refusing rather than writing anything broken

render_preview is the one with no command-line equivalent, and it's the reason a block's Print output stops being guesswork: your agent can look at the page it just changed instead of describing what it hopes is there. What it sees is the print render, so anything that only appears on hover or after a click isn't in the picture, the same as on paper.

A block pack_block writes is packed, not live. It waits for you to approve it like any other new block, unless its capabilities match a version you've already approved, which is the same rule plicine block push follows (Editing an installed block).

The tools are offered over the Model Context Protocol: the Agent Client Protocol has no way to hand an agent tools directly, so Plicine runs a small MCP server on its own local server and names it when it opens a session. An agent that doesn't speak MCP over HTTP simply doesn't get them, and the agent menu says so; everything else works as before. The agent menu also lists the tools a session was given.

AGENTS.md for terminal agents

Everything above needs the app open. AGENTS.md at the vault root closes that gap: it holds the same primer the palette sends, written to a file, so an agent working from a terminal starts with the same picture of the vault.

It's off by default, because it's a generated file in a folder other people sync. Turn it on either way:

  • Write AGENTS.md in the palette's agent menu, which writes the file straight away and keeps it up to date from then on. Settings has the same switch.
  • plicine agents-md <vault> --write, which does the same from a terminal. --remove turns it off again and deletes the file, and the bare command reports where things stand.

Both set agentsMd in .vault/vault.json, so the two agree. While it's on, Plicine rewrites the file whenever the vault's documents, blocks, themes or configuration change, and only when the content would actually differ, the way blocks.lock behaves. An AGENTS.md you wrote yourself is never overwritten: the generated file carries a marker on its first line, and Plicine only touches a file that has it.

The vault root's AGENTS.md isn't a page. It doesn't show in the sidebar, [[links]] don't reach it, and Plicine's own writes to it don't register as a document changing. See Vaults for the rest.

Still to come

The primer doesn't carry block packages' JSON schemas yet, because producing one means running the block's code, which only happens in a sandboxed frame. BLOCK.md is written to cover the same ground, which is why pack warns when a block has no example in it. The trust panel doesn't yet show a code diff for a block an agent changed, so an update is approved on its manifest and its BLOCK.md rather than on what actually changed in its source. Both are planned.