| name | trellis-build-agent |
| description | Build or modify a Trellis agent by editing the agent blueprint, skills, knowledge, state map, MCP surfaces, and verification commands. |
Trellis Build Agent
Use this skill when the user wants to build, modify, or explain a Trellis agent, not just deploy an existing scaffold.
Always fetch/read references/trellis-agent-build-guide.md before making agent-shape changes. That guide is the source of truth for the novice workflow, file map, state model, MCP surfaces, and safe verification order.
Working Model
Trellis agents are built from five files/folders:
src/agent.ts = agent blueprint and workflow.
src/state/*.map.ts = business state projection into Trellis D1 state records.
knowledge/**/*.md = company, ICP, product, messaging, policy, and examples.
skills/**/SKILL.md = repeatable methodology for each bounded skill.
wrangler.jsonc = Cloudflare binding map generated by Trellis.
Do not start by editing Cloudflare internals. Start with the agent behavior, then state, then skills, then knowledge, then verification.
Default Build Order
For a new or changed agent:
- Read
src/agent.ts, src/state/*.map.ts, knowledge/, skills/, wrangler.jsonc, and package.json.
- Identify the user-facing role surface: SDR, operator, author, customer success, support, research, or custom.
- Define the workflow in plain language: signal -> skills -> workflow -> approvals -> side effects.
- Edit
src/agent.ts using Trellis primitives only.
- Add or update
trellis.state(...) projections for business objects.
- Add or update one
SKILL.md per bounded step.
- Add knowledge markdown instead of stuffing context into prompts.
- Configure role-shaped MCP tools in
mcp.tools.
- Keep
trellis.safeOutbound() unless the user explicitly asks to change safety.
- Run typecheck, smoke, deploy, and verify in that order.
Agent Blueprint Pattern
Prefer this shape:
export default trellis.agent("agent-name", {
crm: attio({ map: attioMap }),
research: firecrawl(),
model: "cloudflare/openai/gpt-5.5",
state: stateMap,
mcp: {
name: "trellis-sdr",
surface: "sdr",
operator: { name: "trellis-operator" },
tools: {
include: ["list_leads", "get_lead", "approve_draft", "qualify_lead"],
skillTools: [
{
name: "qualify_lead",
skill: "icp-qualification",
schema: schema.qualification(),
},
],
},
},
knowledge: "knowledge/**/*.md",
skills: "skills/**/SKILL.md",
safety: trellis.safeOutbound(),
}, async (app) => {
const signal = await app.signal();
const context = await app.context(signal);
const qualification = await app.skill("icp-qualification", {
context,
schema: schema.qualification(),
});
return app.workflow("prospect").start({ signal, qualification });
});
State And D1 Rule
Trellis owns the internal D1 schema. Do not hand-write migrations for these tables:
trellis_signals
trellis_state_records
trellis_drafts
trellis_approvals
trellis_provider_runs
trellis_provider_actions
trellis_workflow_runs
trellis_audit_events
trellis_trace_events
trellis_operator_controls
trellis_smoke_runs
trellis_agent_sessions
trellis_slack_threads
Define business state through trellis.state(...); Trellis persists those projections into trellis_state_records.
When the task is about creating D1, checking schema, seeding demo rows, cleaning traces, or proving database contents, switch to trellis-setup-database.
Use fields like:
const stateMap = trellis.state({
tables: {
prospects: {
primaryKey: "id",
fields: {
id: "prospect.id",
signalId: "signal.id",
company: "signal.payload.company",
domain: "signal.payload.companyDomain",
status: "qualification.decision",
summary: "qualification.summary",
},
indexes: [
{ name: "prospects_by_status", fields: ["status"] },
],
},
},
});
Skill Formatting
Each skills/<name>/SKILL.md should be useful to a model and readable by a novice:
# Skill Name
## Purpose
One sentence.
## Inputs
- `signal`
- relevant `knowledge/` files
- prior skill outputs
## Method
1. Check required evidence.
2. Apply the business rules.
3. Return only the expected structured output.
## Output Contract
Return fields that match the schema passed in `src/agent.ts`.
## Safety
Do not send email, mutate CRM, or call side-effect tools. Trellis approvals handle that.
Keep one skill per bounded capability. Do not write a single giant skill that qualifies, researches, drafts, and approves.
MCP Surfaces
Use role-shaped MCPs:
trellis-sdr at /mcp/trellis for business tools.
trellis-operator at /mcp/operator for runtime controls.
The SDR surface should expose business vocabulary like:
list_leads
get_lead
pipeline_stats
estimate_cost
list_pending_approvals
approve_draft
reject_draft
- bounded skill tools such as
qualify_lead or draft_email
The operator surface should expose runtime vocabulary like:
trellis.health
trellis.signal.submit
trellis.trace.inspect
trellis.trace.cost
trellis.operator.controls
- replay, pause/resume, and provider-action tools
Verification Commands
After edits:
npm run typecheck
npm run doctor -- --json
npm run smoke -- --json
npm run deploy -- --json
npm run verify -- --json
npm run verify -- --live --url "$APP_URL" --api-key "$TRELLIS_API_KEY"
Use live exercise only when the user accepts model/runtime cost:
npm run verify -- --live --url "$APP_URL" --api-key "$TRELLIS_API_KEY" --exercise-agent
Response Shape
When finished, report:
- files changed
- agent behavior changed
- MCP tools exposed
- D1/state impact
- safety gates
- verification commands run
- what remains manual, such as Cloudflare secrets