Authoring blueprints
The blueprint is what makes the agent itself — identity, channels, capabilities. Markdown for who it is, JSON for its settings; the same files travel when you ship it.
Three core surfaces under blueprint/: identity (markdown, rides every turn), channels (configured separately under blueprint/channels/<name>/ — see Channels for the model), and props (JSON + a cron text file, server-consumed). Plus two optional add-ons: service/ for host code (covered in Writing services) and assets/ for static read-only data mounted at /assets.
Identity — who the agent is
Four optional markdown files under blueprint/identity/. The server reads each as raw markdown and injects it into the agent's system prompt on every turn. Identity is where most authoring happens — and every line is paid for on every conversation, forever.
prompt.md
Core persona and behavior instructions. Voice, mandate, posture, hard rules. Injected as-is, no wrapper. No required structure; write it like a carefully-worded brief to a new colleague. Keep it scaffolding, not prescription — discipline in Designing well.
whoami.md
Stable identity facts the agent should always know about itself: name, role, preferences, persistent constraints. Conventionally bulleted, but the file is markdown — anything goes. Wrapped in <agent-identity>.
- Name: Smith
- Role: research assistant
- Operator: Alex (timezone: America/New_York)
- Always answer in plain text — no markdown rendering on the client.skills.md
Tool-usage guidance. One short bullet per tool or skill. Tutorial-prose here pays tokens on every conversation that loads the tool. Wrapped in <agent-skills>.
- task__schedule: defer self-actions to a future time; payload becomes the next session's input.
- web__fetch: fetch a URL and clean it through markdown/crawl4ai/raw pipelines.
- message_log__search: search past messages by keyword in the current conversation's history.Peer reach is not authored in the blueprint. Which sibling agents this one may reach is a per-install decision that lives in config/acl.json, and the agent learns its granted peers from an <agent-peers> block the server computes from that ACL. To find peers it could request access to, the agent calls agent__list_peers at runtime. See Multi-agent composition.
Channels — the dynamic surface
Channels are configured under blueprint/channels/<name>/ — one directory per channel, containing channel.json (lifecycle, tools, sharding) and the lifecycle markdown files (prompt.md, bootstrap.md, cleanup.md). Most agents start with just default — the implicit fallback (30 min idle, no lifecycle, logged) is a working user-chat config without any channel.json.
The deep treatment — file shapes, conversation lifecycle, memory continuity, sharding, and when a second channel earns its place — lives on Channels.
Props — settings and capabilities
Three files under blueprint/props/, server-consumed (not mounted into the container).
settings.json
{
"profile": "standard",
"env": { "TZ": "America/New_York" }
}profile is standard or minimal — chooses the behavioral baseline (filesystem conventions, tool descriptions) injected as prompt layers 2–3. env overrides environment variables on the agent runner process.
capabilities.json
Agent-wide tool restrictions, extension declarations, resource-slot declarations, Python package allowlists, external MCP server declarations — everything that decides what the agent can do at all.
{
"disabled_tools": ["bash"],
"additional_disabled_tools": { "unlocked": true, "value": [] },
"pip": {
"allowed_packages": ["requests", "pandas"],
"extra_packages": { "unlocked": true, "value": [] }
},
"resources": {
"notes_dir": { "description": "Author's notes folder", "access": "ro", "required": true },
"scratch": { "access": "rw" }
},
"extensions": {
"email": {
"enabled": true,
"channel": "email",
"send_mode": { "unlocked": true, "value": "disabled" },
"read_window_days": { "unlocked": true, "value": 7 }
}
},
"mcp_servers": {
"github": {
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": { "unlocked": true, "required": true, "description": "PAT with repo scope" },
"GITHUB_API_VERSION": "2022-11-28"
}
}
}
}Several fields take one of two forms: a bare value (locked — the operator can't override it) or { unlocked: true, value: ... } (operator-fillable). The pattern shows up on additional_disabled_tools, pip.extra_packages, MCP env slots, and individual extension config fields. The decision is yours: lock fields that are part of the agent's identity or safety contract; unlock fields that legitimately vary per install — a credential, a calendar URL, the hour of a daily digest. Operator writes to locked fields are silently ignored at merge time.
Slots and unlocked fields declared here are filled in by the operator — resources and pip in config/provisions.json, MCP env values in config/mcp-servers.json, extension overrides under config/ext/<name>/. See Configuring agents. The deep treatment — what extensions are, how they differ from MCP, when to reach for an agent service — is on Capabilities.
schedule.txt
One line per scheduled self-message. Standard 5-field cron expression, then target channel (optionally name/qualifier for sharded channels), then the message text. Lines starting with # are comments.
# minute hour dom month dow channel[/qualifier] message text...
0 9 * * * default Time for the morning briefing.
30 17 * * 5 reflection Friday wrap-up — what shipped this week?
*/15 * * * * default/poll Check the inbox.Messages are self-addressed — the agent receives its own message on the named channel. For cadences the agent or user decides at runtime, use the task__schedule MCP tool instead; schedule.txt is for cadences the author fixes.
Agent-wide vs channel-specific
Each directive belongs in one place — identity for rules that apply to every channel, the channel folder for rules that only apply to one.
- Would this be true on every channel the agent will ever have? → identity (
prompt.md). "Always summarize before closing," "never write outside /memory/." - Does it depend on which entry point is in play? → channel (
channels/<name>/prompt.md). "Wrap turns in <cast:internal> unless something genuinely warrants the user" only makes sense in a quiet processing channel. "On first turn, load the previous run's summary" belongs inbootstrap.md.
Agent service
An agent service is where Cast's ceiling actually sits — host-side code under blueprint/service/ that wraps any system (an internal API, a CLI, a private search index, a webhook listener) and exposes it to the agent as tools. It's how a Cast agent gets reach into the systems you actually work in.
Extensions stay the curated path — email, calendar, web-fetch, whatsapp — engineered for safety and token discipline, ready for anyone. A service is the open path: full credentials on the host, every safeguard you write yourself. The trade-off is the deal, and the reason it's a power-user surface. The deep treatment is in Writing services.
What to read next
- Configuring agents — the companion: how the blueprint gets wired to your install (model, ACL, secrets).
- Channels — what each
blueprint/channels/<name>/folder configures, and the patterns multi-channel agents enable. - Capabilities — extensions, agent services, external MCP; when to reach for which.
- Multi-agent composition — when one agent isn't enough; how channels become the contract between them.
- Designing well — the discipline above the parts.