Instructions for every agent
Your app's prompts, per-turn context and skills reach Claude, Codex, Cursor, Grok and OpenCode — how each provider receives them, the size budget, and how to write instructions that work for all of them.
Users pick their agent per chat: Chataway's own chat, Claude Code, Codex, Cursor, Grok or OpenCode. What your app tells the agent reaches whichever one they picked — so write it for all of them.
#What reaches the agent
| From your app | What it is | Who can use it |
|---|---|---|
| Tool descriptions | When and how to call each tool | Every app (contributes.tools[].description for cloud apps) |
ctx.prompts.register(text) | Standing instructions for the whole conversation | Local apps |
ctx.agentContext.register(fn) | A line of context for this turn — "the user selected todo 3" | Local apps |
| Skills | Longer playbooks in .claude/skills/<name>/SKILL.md | Apps that install skills (local apps, Claude Code plugins from GitHub) |
| Companion lines | Which apps and connectors your app works with are on right now | Every app with requires (added by Chataway) |
Card answers the agent hasn't picked up yet (the user tapped Approve after the tool stopped waiting) arrive the same way as per-turn context.
#How each provider receives it
| Provider | Standing instructions | Skills | Per-turn context |
|---|---|---|---|
| Chataway chat | System prompt | Found natively | System prompt, per message |
| Claude Code | MCP server instructions + appended system prompt | Found natively | A prompt hook, per message |
| Codex | Developer instructions, every turn | Listed in the instructions | Appended to the user's message |
| OpenCode | The system field, every turn | Listed in the instructions | Appended to the user's message |
| Cursor | A preamble on the first message, re-sent when it changes | Listed in the preamble | Appended to the user's message |
| Grok | A preamble on the first message, re-sent when it changes | Listed in the preamble | Appended to the user's message |
For Codex, OpenCode, Cursor and Grok, Chataway composes one block per chat: every on app's prompts that serve that provider, then a skills index — each skill in the workspace with its one-line description and the path of its SKILL.md, and the rule read the SKILL.md before a matching task. Preambles ride in the agent's copy of the message only; the user never sees them in the chat, and nothing is written into their repository (no AGENTS.md, no edited config).
Per-turn context goes after the user's text, marked as coming from Chataway:
Find the cheapest flight.
<chataway_context>
Context from the user's Chataway apps for this message (added by Chataway, not typed by the user):
The user has selected trip "Lisbon, May 12–16".
</chataway_context>#The budget
For Codex, OpenCode, Cursor and Grok the whole block — all apps' prompts plus the skills index — is capped at 6,000 characters. When there are prompts, the skills index gets at most 40% of that (descriptions are dropped first, then names beyond the room). Prompts that don't fit are cut, with a pointer to the skill files.
You share that budget with every other app the user has on. Aim for a few hundred characters; put anything long in a skill and point at it.
ctx.agentContext providers must answer within 1.5 seconds; return null when there's nothing to say.
#Write it provider-neutral
// ✗ Claude-only, and long
ctx.prompts.register(`Use the Bash tool to run curl against api.acme.dev, then WebFetch the result…`);
// ✓ names your own tools, gives a fallback, stays short
ctx.prompts.register(
'For Acme orders use list_orders and make_poster. ' +
'If those tools are not available, say so and stop — never call the Acme API directly. ' +
'Full poster guidelines: the acme-posters skill.',
);- Name your own tools, never a provider's (
Bash,WebFetch,mcp__…). Agents see your tools under their own prefixes; the plain tool name is enough. - Give a fallback for a missing tool — a connector the user skipped, a provider without app tools: "If the Canva tools aren't available, say so and use the browser."
- Say what, not how. Every agent has its own file and shell tools; "read the SKILL.md" works everywhere, "use the Read tool" doesn't.
- Keep it short. Long how-tos belong in a skill, which only costs a line in the index.
- Limit it if you must.
ctx.prompts.register(text, { providers: ['codex'] })targets some providers;requires.providersin the manifest limits the whole app. Most apps shouldn't.
Tool descriptions follow the same rules: they're the one piece of your app every agent reads before choosing a tool. Say when to use the tool, what it does and what it costs.