Building a team
How to write a team definition file, publish it to the Library, and manage it entirely via the API — no editor required.
Authenticate every request with your API key:
Authorization: Bearer <your-api-key>All endpoints are prefixed with /api. The base URL is your Envelope instance origin (e.g. https://openenvelope.org/api).
1. Write the definition
A team definition is a JSON object describing the team's name, agents, required secrets, required variables, access policy, and pricing. The full schema is published at:
https://schema.openenvelope.org/team/v1.jsonAdd a $schema reference to your file and your editor validates against it automatically.
Minimal valid definition:
{
"$schema": "https://schema.openenvelope.org/team/v1.json",
"name": "Support Triage",
"description": "Routes inbound support tickets to the correct queue based on urgency and topic.",
"agents": [
{
"key": "coordinator",
"name": "Triage Coordinator",
"title": "Coordinator",
"role": "Receives incoming ticket text and routes it to the correct specialist.",
"model": "anthropic:claude-sonnet-4-5",
"systemPrompt": "You are a support triage coordinator. Analyse the ticket and output a routing decision."
}
],
"requiredSecrets": ["ZENDESK_API_KEY"],
"requiredVariables": ["QUEUE_EMAIL"]
}Agent hierarchy
Connect agents with reportsToKey. The agent with no reportsToKey is the coordinator — all others report up through the hierarchy.
{
"agents": [
{ "key": "coordinator", "name": "Coordinator" },
{ "key": "specialist-a", "name": "Tier 1 Specialist", "reportsToKey": "coordinator" },
{ "key": "specialist-b", "name": "Escalation Specialist", "reportsToKey": "coordinator" }
]
}Keep hierarchies shallow. One coordinator with 2–4 specialists is the most common pattern. Deep hierarchies add latency and complicate debugging.
Access policy
Declare which outbound hosts each agent may call. Deployers and their security teams can review this in the Library before installing. An explicit policy — even a permissive one — builds more trust than no policy.
{
"agents": [
{
"key": "coordinator",
"accessPolicy": {
"default": "deny",
"rules": [
{ "host": "api.zendesk.com", "methods": ["GET", "POST"], "effect": "allow" }
]
}
}
]
}Adapter types
By default Envelope chooses the adapter. Override per-agent with adapterType:
{
"agents": [
{ "key": "coordinator", "adapterType": "claude_local" }
]
}Supported values: claude_local, codex_local, gemini_local, opencode_local, cursor_local, openclaw, process, http.
2. Create a draft
POST /templates{
"slug": "support-triage",
"name": "Support Triage",
"description": "Routes inbound support tickets to the correct queue based on urgency and topic.",
"visibility": "private",
"category": "support",
"definition": { ... }
}| Field | Required | Description |
|---|---|---|
slug | Yes | URL-safe identifier. Must be globally unique. Min 2 chars. |
name | Yes | Display name shown in the Library. Min 2 chars. |
description | Yes | Short summary shown in search results. Min 10 chars. |
visibility | No | "private" (default), "team", or "public" |
category | No | Functional category, e.g. "support", "sales", "ops" |
targetPlatform | No | Platform the team is optimised for, e.g. "paperclip", "bedrock" |
definition | Yes | Full team definition object (see above) |
Response: 201 Created — returns the full template object including the assigned id. Store this id — you'll use it in every subsequent call for this team.
A slug collision returns 409 Conflict. Choose a different slug.
3. Update the draft
PATCH /templates/:id{
"description": "Routes tickets and escalates P1s automatically.",
"definition": { ... }
}Only draft status templates can be patched. Attempting to patch a published template returns 409. Create a version draft first — see Versioning your team.
Updatable fields: name, description, visibility, pricingModel, priceUsdCents, forkable, changeLog, definition.
4. Set pricing
Update via PATCH /templates/:id:
{
"pricingModel": "per_run",
"priceUsdCents": 50
}pricingModel | Description |
|---|---|
"free" | No charge to deployers |
"per_run" | Fixed charge per run trigger |
"per_k_tokens" | Charge per 1,000 tokens consumed across the run |
priceUsdCents is the amount in US cents charged to deployers. Envelope's platform fee is deducted automatically before payout. See Pricing your team for fee details and payout mechanics.
5. Publish
POST /templates/:id/publish{
"changeLog": "Initial release. Routes tickets by urgency using keyword detection."
}Always supply a changeLog string. It is shown to deployers in the Library and in their install's version history — a blank changelog makes upgrade decisions harder for everyone who installs your team.
Response: Returns the updated template with status: "published" and a version number. The team is now visible in the Library and installable by ID or slug.
Envelope validates your definition against the JSON Schema on publish. A 400 error includes specific field-level messages. Fix those and re-publish.
6. List your teams
GET /templates/allReturns all templates owned by your API key — drafts, published, and archived — ordered newest first.
7. Get a team
GET /templates/:idReturns the full template including definition and system prompts. Other callers receive a stripped version without prompts.
Model routing
Envelope assigns a model to each agent automatically based on its role. Builders can pin a specific model in the definition, and deployers can override any agent's model at the install level — without touching the team definition.
Setting a default model in the definition
Set model on any agent in provider:model format. This becomes the default for all installs of this team, but deployers can override it:
{
"agents": [
{ "key": "triage", "model": "openai:gpt-5-mini", "role": "classify incoming tickets" },
{ "key": "responder", "model": "anthropic:claude-sonnet-4-5", "role": "draft replies" }
]
}How the resolution order works
For each agent, Envelope resolves in this order:
- Deployer override — set via API or workspace UI — wins over everything
- Definition model — the
modelfield you set above - Auto-routing — Envelope assigns a tier based on role keywords (orchestrators get frontier models, classifiers get efficient ones, etc.)
If you want Envelope's model router to decide for an agent, omit the model field entirely.
Deployer model override API
Deployers can inspect and change model assignments per-agent without forking or re-installing:
GET /api/installs/:installId/agents — list all agents with effective models
PATCH /api/installs/:installId/agents/:key/model — pin a model override
DELETE /api/installs/:installId/agents/:key/model — reset back to auto-routingSee Installing a team for details.
Common mistakes
Not validating the definition before publishing — run the JSON Schema validator locally first. Envelope validates on publish and returns specific field errors, but catching them locally is faster.
No access policy — teams with no policy look opaque to deployers who need to justify network access to their security teams. Even a permissive "default": "allow" policy is better than nothing.
Blank changelog — every release your deployers track needs context to decide when to upgrade. Write something meaningful even for small changes.
Wrong version bump for breaking changes — removing a field, renaming an agent key, or making an optional input required are all breaking changes. When in doubt, bump MAJOR. See Versioning your team.