Instructions, rules, agents, docs, and team
The markdown contribution categories and how each reaches the system prompt.
Beyond tools and
skills, a package contributes plain markdown
that shapes agent behavior. Five first-class categories become typed arrays on
the package definition — skills, instructions, rules, agents, docs —
plus team members. Each markdown contribution lives in its category folder,
needs a frontmatter name (or id) to be discovered, and carries its
category from the folder, never from frontmatter (see the
directory contract).
Category cheat-sheet
| Folder | Category | Reaches the model as | Use for |
|---|---|---|---|
rules/*.md | rule | Always-on system-prompt block, near the top | Hard constraints the agent must always obey |
instructions/*.md | instruction | System-prompt block, grouped with rules | How-to guidance and workflows |
docs/*.md | docs | Listed in the package overview (title + description); read on demand — not injected by default | Background and reference material |
skills/<name>/SKILL.md | skill | Advertised in the package overview; body rendered on activation | Procedural capability bundles |
agents/*.md | agent | Spawnable delegate persona | Sub-agent identities |
Workflow templates (workflows/*.json)
A template's optional execution policy can declare a model id, reasoning effort, an exact catalog-declared base or extended context override, and fast mode. Template and persisted contract values are null-free: omission means inherit from the target agent. Clearing is a runtime update operation, not an authored template value, and explicit false means fast mode is off. Provider capability validation is performed by the consuming workflow runtime rather than duplicated in the package kernel.
Packages can also ship workflow templates — blueprints for scheduled or
recurring agent runs. These are deliberately not a markdown category:
workflows/*.json becomes a parallel typed array (PackageWorkflow[]) like
tools, is validated strictly at load (an invalid template fails the package
load), and is never injected into the system prompt. The model reaches
templates only through the workflow routes, with the manage-workflows skill's
template scripts (list, install, upgrade); users reach them through the same
routes and the Calendar's template browser.
A template declares its id (from the filename), a title and description, a
defaultInstructionTemplate, and optional defaultTriggers. All four trigger
kinds are authorable — manual, schedule (a cron expression or a once
timestamp, both bounded by endAt, cron additionally by maxRuns), webhook,
and message — while the engine-runtime fields inside a trigger (fire counters,
next-fire time, webhook token material) are rejected at validation. An optional
inputs map describes its {{PLACEHOLDER}} parameters using the GitHub-Actions
workflow_dispatch.inputs field names (description, required, type
string/choice/boolean, default, options); three placeholder names are
engine-owned and rejected as input keys — WORKFLOW_DIR,
WORKFLOW_STATE_URI, and FIRE_TIME, all substituted at fire time. An
optional requires.features visibility gate carries the same semantics as
requiredFeatures on markdown contributions.
The rest of the shape is presentation and per-entry defaults: icon, color
and group for the calendar and the template catalog; teamMemberSlug
names a packaged team member's agent (validated, but no runtime reads it yet); defaultStateMode (fresh
starts each run clean, continue keeps the run conversation); a
defaultExecutionPolicy (maxConcurrent, maxRuntimeMs, and optional
modelId, reasoningEffort, contextWindowOverride, fastMode); a defaultSessionSetup carrying the run's goal and loop bounds;
and requiredCredentials, the credential-catalog ids the instruction's skills
and tools will need.
A template may also declare a delivery intent (announce / webhook /
none) and the channelKinds it expects to deliver to: an announce
template installs with announce delivery already enabled on the entry, and
the install surfaces show the channel hint — actual routing still requires an
explicit channel binding created by the user. Cron defaults always carry the
UTC timezone (template inputs never reach triggers, so a shipped cron must
not depend on install-time locale) — say so in the description and let users
edit the schedule after install.
Installing a template validates the supplied inputs, substitutes them into
the instruction, and creates a draft workflow owned by the installing
user — every later fire runs with that user's current permissions. Disabling
the source package suspends installed workflows at their next fire instead of
running them; re-enabling does not auto-resume. If your package ships
templates, remember to add workflows to the package.json#files whitelist.
A template may carry an optional revision (a positive integer; omitting it
means revision 1). Because installing copies the instruction into the
workflow rather than live-linking it, bumping a shipped template's revision
is how you signal that already-installed copies are stale: the platform pauses
an out-of-date active copy (surfacing an "upgrade required" reason) rather than
silently rewriting a user's installed instruction. Someone allowed to edit that
workflow then upgrades it in place — it keeps its identity, run history and state
— and resumes it after reviewing the new text.
Declared sources (sources[])
Like workflow templates, declared sources are a parallel typed array on the
package definition (sources[]), not a markdown category and never injected
into the prompt. Each entry declares a concrete filesystem source instance — of
a connector kind already registered via connectors[] — that the platform
seeds into every project (seed: "auto") or offers for on-demand add
(seed: "discoverable"). Declarations are trust-gated at load, and the
declaring package becomes the source's origin attribution. Full reference:
Connectors → Declaring sources.
Prompt-injected categories
Rules and instructions are injected into the system prompt for every turn, each
wrapped in a <package_file> block that carries its category, id, owning
package and title:
<package_file category="rule" id="mutation-safety" package="brain-core" title="Mutation safety">
...the file body, without its frontmatter...
</package_file>The frontmatter is dropped when every key in it is one the platform renders
itself (id, name, title, description, activation, requiredFeatures,
defaultEnabled, overwrite). Any other key keeps the whole file, frontmatter
included — an imported rule's scope (paths, applyTo, globs) still reaches
the model that way. A file the prompt already carries is named in the package
overview without repeating its description.
They render near the top of the prompt (primacy). Within each group, files sort
by category priority and path; each file's content is capped at injection time
by the packageFileMaxChars platform setting (default 8,000 characters,
admin-tunable). Flat {{conversationId}}, {{agentId}}, {{projectId}}, and
{{userId}} placeholders substitute at injection; dotted forms such as
{{user.name}} ship literally and should not be used.
docs/*.md are not injected. They are listed in the package overview by
title and description, and the agent reads them on demand — the same lazy model
as a skill body. A built-in package's doc is read through the agent-core
inspection skill (files.sh content <package> <category> <id>), which serves only
an active file the caller's own catalog lists; a project-installed or source
package's doc is read with fs_read on its URI. (An author can force a single doc into the
prompt with frontmatter activation.pinned or activation.target: "prompt-context", but this is rare and discouraged: put behavioral content in
rule/instruction and leave reference in plain docs.)
Because injected files cost tokens on every turn, keep rules and
instructions tight, push long reference into docs (read on demand), and put
procedural detail into a skill body — a skill renders only on activation.
Rules are a first-party privilege
For any package below first-party trust, discovery downgrades rules/
contributions to docs. A project-installed package can ship reference
material, but it cannot inject always-on behavioral constraints into the
system prompt.
Agents — delegate personas
An agents/*.md file defines a persona the platform's delegate tool can
spawn as a sub-agent. The file body becomes the child agent's system prompt;
frontmatter name, allowed-tools, and model are honored when the run is
created — and on a persona an explicitly empty allowed-tools: [] is honored
too, as a child with no tools, while omitting the field inherits the caller's
own set. On a persona the list is a ceiling: a delegate call naming its
own tools is intersected with it and can only narrow, the dropped names are
reported back in the result, and a call asking for none of them is refused. The delegate tool resolves a requested agent by id or name from the
first-class agent array, falling back to skill-forks — skills whose frontmatter
declares context: fork register in the agent category and resolve the same
way.
---
name: reviewer
description: Reviews a change set against the project conventions.
allowed-tools: [fs_read, fs_search]
---
You are a meticulous code reviewer. Inspect the files you are pointed at...The child run inherits the parent's package enablement and the caller's real identity and grants — a delegate never escalates beyond what the calling user could do.
Docs
docs/*.md is the category for material the agent should be able to consult
without obeying it as a constraint: API references, background, lookup tables.
Docs are not auto-injected into the prompt: they are listed in the package
overview by title and description and read on demand, exactly like a skill body.
This category is also the landing spot for anything trust-sanitized out of
rules/.
Team members
team/<slug>/ ships a ready-made agent character — package-provided base
configuration for the agent-creation flow:
team/
search-agent/
member.json # slug, name, role, description, config, permissions, appearance
identity/ # *.md identity files injected for this member
files/ # *.md additional member filesmember.json carries the create-agent shape:
{
"slug": "search-agent",
"name": "Search",
"role": "assistant",
"description": "What this coworker is for, and when to pick it.",
"config": {
"settings": {
"maxSteps": 15,
"defaultModelId": "provider/model-id",
"guardProfile": "balanced"
}
},
"permissions": { "sources": ["brain"], "features": ["core.agents"] },
"appearance": { "icon": "search", "color": "#3b82f6" }
}Four rules that are easy to get wrong:
descriptionis the field that reaches a model. A member may also carrydescriptionForModel, but nothing reads a member's copy — only the package-leveldescriptionForModelis advertised. Put the "when to pick this coworker" sentence indescription.- Pin a model and a guard posture inside
config.settings, asdefaultModelIdandguardProfile. There is no top-levelmodel,icon, orcolorkey — appearance nests underappearance. - Identity placeholders substitute once, at provisioning. When an agent is
created from the member, each
identity/*.mdandfiles/*.mdis copied into the agent's own data directory with a fixed eight-key substitution:{{agentId}},{{agentName}},{{createdAt}},{{packageId}},{{memberSlug}},{{role}},{{projectId}},{{userId}}. There is no per-turn re-substitution, and{{conversationId}}is not in the set — write it and it ships to the model literally. Dotted forms such as{{user.name}}ship literally everywhere. - Identity-file frontmatter is stripped, not parsed.
activation,pinned, andpriorityon an identity file do nothing; injection order is fixed by filename, so name the files in the order you want them read.
A team directory without a member.json is skipped.
Visibility
Every category obeys the same two gates, deny-by-default:
- Package state — a disabled package's contributions are not injected, not advertised, and not listed.
- Caller grants — a contribution may declare
requiredFeatures: [a, b]in frontmatter (flat flow array). A caller missing any listed feature never sees it: not in the prompt, not in the package overview, not in the files catalog. Hidden means hidden — gated contributions are never rendered as locked or off, so non-holders cannot infer they exist.
The predicate and grant model are described in Features and access.
Within those gates, every file contribution of every package is also individually toggleable at two scopes: agent scope in the packages editor, and conversation scope in the composer's package selector, where every package row expands into per-file rows (opt-in files badged). An agent-level per-file off is final — a conversation cannot re-enable it. The full precedence chain is described with the source-package defaults on Source packages.
Source-contributed packages
A synced filesystem source can contribute the same five categories too — no
package.json required. A mounted repository's .claude/ or .cursor/
folder, a directory of skills/ and rules/, or a free-standing SKILL.md
folder groups into a source package that behaves like any other package,
with deliberate defaults (source rules and identity files are opt-in, docs
are never auto-injected) and per-file toggles at both agent and conversation
scope. The full story — recognized layouts, grouping rules, defaults,
skill activation, and the security model — is on
Source packages.