How to write great agent instructions for an agent-native app or template: AGENTS.md, skills, and tool/action descriptions. Use when authoring or reviewing AGENTS.md, writing a SKILL.md, wording action descriptions, or deciding what belongs in instructions vs skills vs memory.
67
82%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
This is a creator-facing guide. When you build an agent-native app or template,
the agent's behavior is only as good as the instructions you give it. Three
surfaces carry that guidance: AGENTS.md (the map), skills (the deep dives),
and action/tool descriptions (how the agent picks the right tool). Write each
one for fast retrieval, not for prose.
AGENTS.md is loaded as orientation. It should be the smallest thing that lets
the agent act correctly, with everything deep pushed into skills. Aim for these
sections and little else:
navigation/selection/focus keys the agent
reads to know what the user is looking at, with their shape.If a section is growing past a screen, it belongs in a skill. AGENTS.md
answers "what is this app and what can I do," not "how exactly do I do the hard
thing."
A template AGENTS.md is injected into the runtime agent's system prompt and
hard-sliced at COMPACT_PROMPT_RESOURCE_MAX_CHARS (6,000). Past that, the agent
sees a truncation marker instead of your text, so the tail stops being
always-on guidance and becomes something it has to go fetch. pnpm the repository's guard:agent-chat-context` check fails the build when a first-party
file overflows; generated apps do not ship that repository-only guard. Keep files
under ~5,500 so ordinary edits don't tip them over.
Two consequences worth designing around:
**/AGENTS.md and **/SKILL.md are in .prettierignore for this reason;
keep them there and write table rows unpadded.# Projects App
One workspace for projects, tasks, and notes. Agent and UI share the same SQL
data and the same actions.
## Core Rules
- Data lives in SQL via Drizzle. Use actions for all writes.
- All AI work goes through the agent chat; never call an LLM inline.
- Schema changes are additive only.
## Application State
- `navigation.view`: `home` | `project`
- `navigation.projectId`: selected project on a project page
## Actions
| Action | Purpose |
| ---------------- | --------------------------- |
| `list-projects` | List accessible projects |
| `create-project` | Create a project |
| `update-project` | Rename or archive a project |
## Skills
- `project-imports` — read before importing legacy CSV exports.
- `sharing` — read before exposing a project to other users.Keep one canonical instructions file: AGENTS.md. If a client expects
CLAUDE.md, make it a symlink to AGENTS.md rather than a second copy. Two
hand-maintained files drift, and the agent ends up with contradictory rules.
One source of truth, linked where needed.
Framework guidance is authored once in this repo and copied outward. Treat
.agents/skills/ as the canonical source for shared skills. Generated
workspace skills in packages/core/src/templates/workspace-core/.agents/skills/
and first-party template copies of shared skills must stay byte-for-byte in
sync; run pnpm sync:workspace-skills after editing a shared skill, and
pnpm guard:workspace-skills before calling the guidance done.
Generated app and workspace instructions must teach the same action-first data contract:
defineAction files in actions/.useActionQuery, useActionMutation, or
callAction; route paths are a transport detail hidden behind helpers./api/* routes are only for route-shaped protocols such as uploads,
streaming, webhooks, OAuth callbacks, public SEO/OG endpoints, or binary
assets.Treat the initial prompt and tool catalog as a latency budget. The agent should start with a compact map of the app, then retrieve depth only when the task needs it.
initialToolNames to the small set of actions used in the app's primary
workflows. Keep tool-search available so every other registered action and
connected MCP tool remains discoverable on demand.AGENTS.md. Put workflow detail
in skills and long reference material in references/ or workspace
resources that the agent can read when relevant.systemPrompt or extraContext. Inject a
bounded summary, stable ids/paths, and the exact action or resource lookup
that retrieves the full content.tool-search.view-screen concise. Return navigation, selection, visible summary,
and ids needed for a follow-up read rather than full record bodies.The goal is progressive disclosure, not reduced capability: a compact first request, precise discovery, and full fidelity once the agent knows which depth is relevant.
Current-generation models do not need a rule repeated in the system prompt, the instructions, and the tool description. Repetition is not reinforcement — it is three chances to disagree with each other, and the model spends effort reconciling them before it can act. Pick the owning layer:
| Layer | Owns |
|---|---|
System prompt / AGENTS.md | Which capabilities exist, and policy spanning tools: turn shape, what to do first, invariants that hold every turn |
| Tool / action description | How to call it, argument and result semantics, what to say about a result, when this tool rather than a sibling |
| Skill | Multi-step workflows, worked examples, field references, edge cases |
The common mistake is restating a tool's mechanics as a numbered core rule.
Deferred tools are loaded through tool-search, so the model always reads the
description before it can call the tool — a start/update/complete sequence or an
argument enum in the prompt buys nothing and is charged on every turn. State
that the capability exists and when it applies; let the description carry how.
Blanket prohibitions were how older models were kept out of worst-case behavior. They now mostly cost accuracy, because a rule stated absolutely is wrong for some fraction of requests and the model has to guess which fraction it is in. Write the intent and let the model apply it:
.describe() on every field. Keep a literal example only where it defines a
syntax the schema cannot, such as a pnpm action CLI invocation in dev mode.When documenting version history, restore, or audit trails, use actions for
full restorable snapshots (list-<resource>-versions,
get-<resource>-version, restore-<resource>-version). Do not copy legacy
raw-route version panels, such as document-version /api/* helpers, into new
features. The Plans version-history pattern is the preferred model.
The description is the only thing the agent sees when deciding whether to read
a skill. It must answer two questions: what the skill covers, and when to
trigger it. A description that only describes the topic will not fire.
---
name: project-imports
description: >-
How to import projects from the legacy CSV export. Use when the user uploads
a project CSV or asks to migrate projects from the old system.
---An optional scope field decides which agent loads the skill:
both (default when omitted) — loaded by connected repo agents and the
in-app runtime agent.runtime — loaded only by the in-app runtime agent.dev — for the human's coding agent (e.g. Claude Code) only. A scope: dev
skill is invisible to the runtime agent everywhere (system-prompt skills block
and docs-search).Use scope: dev for internal-only guidance that should help connected repo
agents such as Codex or Claude Code, but should not influence the deployed
production agent. Do not use metadata.internal for this: it is catalog/package
metadata and does not control runtime visibility.
---
name: release-checklist
description: >-
Steps for cutting a release. Use when preparing or publishing a new version.
scope: dev
---Omit scope for normal skills (the default both keeps them loading at
runtime — fully backward compatible). For a dev-only skill, mark it scope: dev
and optionally mirror it under .claude/skills/<name>/SKILL.md so Claude Code
picks it up while the runtime agent skips it.
Write the SKILL.md as the lean, must-know layer: the rule, how to do it, the
do/don't list, and pointers. Push long examples, exhaustive field references,
API quirks, and edge-case tables into references/ files the agent reads only
when it needs them.
.agents/skills/project-imports/
├── SKILL.md # rule + happy path + do/don't
└── references/
└── csv-format.md # full column spec, encodings, edge casesThis keeps the always-loaded surface small and lets depth scale without bloating context. See the create-skill skill for the full skill format.
The agent scans tables faster than prose. Prefer a table of name -> purpose over paragraphs describing each operation. The same applies to state keys, field types, and any enumerable set. Tables are skimmable, diffable, and easy to keep in sync when you add an action.
Action descriptions are tool descriptions — they drive tool selection. Make each one a precise, single-purpose sentence:
.describe() so the agent fills it correctly.readOnly: true / http: { method: "GET" }) so the
agent knows they're safe to call freely.provider-api-catalog, provider-api-docs, and
provider-api-request instead of implying the shortcut is all the agent can
do.defineAction({
description: "Create a project. Returns the new project id and title.",
schema: z.object({
title: z.string().min(1).describe("Project title shown in the sidebar"),
}),
// ...
});App instructions should make honesty and verification the default behavior:
view-screen) instead of assuming
the write worked.Put these as core rules in AGENTS.md so they apply to every turn.
Instruction authors must make credential handling explicit anywhere an app, skill, action, webhook, integration, or extension touches external services. Write the rule in terms of values, not just files: never hardcode real API keys, tokens, webhook URLs, signing secrets, OAuth refresh tokens, private Builder/internal data, or customer data in source, docs, tests, fixtures, prompts, screenshots, or generated content.
Examples may name credential keys such as OPENAI_API_KEY or SLACK_WEBHOOK,
but values must be placeholders (<OPENAI_API_KEY>, ${keys.SLACK_WEBHOOK}) or
clearly fake test data. Tell agents which approved channel to use instead:
deployment env vars for deploy-level secrets, app_secrets /
saveCredential / resolveCredential for scoped API keys, oauth_tokens for
OAuth, and ${keys.NAME} substitution for extension/automation outbound HTTP.
memory/MEMORY.md) — per-user preferences and corrections, not
authored guidance. See capture-learnings.AGENTS.md to roughly one screen of orientation; link out for depth.AGENTS.md — point to the skill.CLAUDE.md to AGENTS.md.view-screen pattern.e9a2f0e
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.