Documentation Index
Fetch the complete documentation index at: https://docs.pinata.cloud/llms.txt
Use this file to discover all available pages before exploring further.
manifest.json lives at the root of every agent’s workspace. It controls identity, lifecycle scripts, secrets, skills, routes, channels, scheduled tasks, and (for templates) marketplace metadata. This page documents every field at the version 1 schema.
The schema is published at:
https://agents.pinata.cloud/schemas/manifest.v1.json
Add a $schema line so editors can autocomplete and validate:
{
"$schema": "https://agents.pinata.cloud/schemas/manifest.v1.json",
"version": 1,
"engine": "openclaw",
"agent": { "name": "My Agent" }
}
Top-level fields
| Field | Type | Required | Description |
|---|
$schema | string | optional | Schema URL for editor support |
version | integer | yes | Manifest version - currently 1 |
engine | string | optional | Container engine - openclaw (default) or hermes |
agent | object | yes | Agent identity (see below) |
model | string | optional | Default model in <provider>/<model> form |
secrets | array | optional | Encrypted credentials this agent requires |
skills | array | optional | Up to 10 skill slugs or CIDs |
tasks | array | optional | Up to 20 scheduled tasks |
scripts | object | optional | Lifecycle hooks (build, start) |
routes | array | optional | Up to 10 port-forwarding rules |
channels | object | optional | Messaging channel configuration |
template | object | optional | Marketplace listing metadata (only for templates) |
agent
Defines the agent’s identity. All fields are written into the workspace (mostly IDENTITY.md) at deploy time.
"agent": {
"name": "Social Bot",
"description": "You manage Socials",
"vibe": "Resourceful and opinionated",
"emoji": "🤖"
}
| Field | Type | Limit | Notes |
|---|
name | string | 1-100 chars, required | Display name |
description | string | ≤ 10000 chars | Personality / role |
vibe | string | ≤ 200 chars | One-line tagline |
emoji | string | ≤ 32 chars | Visible in lists and avatars |
model
A single default model identifier in <provider>/<model> form:
"model": "anthropic/claude-sonnet-4-6"
Provider must match a connected provider in the Secrets Vault. If a task or session specifies a model that isn’t enabled on the agent, the request falls back to this default.
secrets
Declares the secrets this agent needs. These are env-var names - the actual values come from the Secrets Vault at attach time.
"secrets": [
{ "name": "OPENROUTER_API_KEY" },
{ "name": "TELEGRAM_BOT_TOKEN", "description": "BotFather token", "required": false }
]
| Field | Type | Notes |
|---|
name | string | Environment variable name (e.g. ANTHROPIC_API_KEY) |
description | string | Shown on the deploy form |
required | boolean | Default true. false makes the field optional in the deploy wizard |
skills
Up to 10 skills. Each entry is an object with a name plus either a clawhub_slug (resolves to the latest published version) or a cid (byte-stable, pinned to a specific upload).
"skills": [
{ "clawhub_slug": "@pinata/api", "name": "Pinata API" },
{ "clawhub_slug": "@pinata/memory-salience", "name": "Memory Salience" },
{ "cid": "bafybeicglyjdb6wrrcbfyu6i2fe4lpxdxgvfvlht7yzdim7cvwt656whue", "name": "My Custom Skill" }
]
| Field | Type | Notes |
|---|
name | string | Display name shown in the UI. Required. |
clawhub_slug | string | ClawHub slug like @pinata/api. Mutually exclusive with cid. |
cid | string | IPFS CID of an uploaded skill. Mutually exclusive with clawhub_slug. |
Each attached skill is unpacked under workspace/skills/<skill-name>/. See Skills.
tasks
Scheduled prompts. Up to 20 per agent. Full reference in Tasks.
"tasks": [
{
"name": "daily-check-in",
"schedule": { "kind": "cron", "expr": "0 9 * * *", "tz": "America/Los_Angeles" },
"payload": { "kind": "agentTurn", "text": "Summarize yesterday." },
"delivery": { "mode": "announce", "channel": "telegram", "to": "123" }
}
]
Schedule kinds: at (one-shot ISO timestamp), every (everyMs interval, optional staggerMs), cron (expr with optional tz).
Payload kinds: agentTurn (chat message; supports model, thinking, timeoutSeconds) or systemEvent (system trigger; provide message).
Delivery modes: none (default), announce (to a channel - set channel and to), or webhook (set to to a URL). bestEffort: true swallows delivery failures.
sessionTarget is main or isolated. wakeMode is now or next-heartbeat.
scripts
Lifecycle hooks. Both fields are shell commands run by the agent’s runner.
"scripts": {
"build": "cd workspace/projects/app && npm install --include=dev",
"start": "cd workspace/projects/app && npx vite --host 0.0.0.0"
}
| Hook | When it runs | Working directory | Output log | Timeout |
|---|
build | After deploy, after each git push, on Retry Scripts | /home/node/clawd | /tmp/user-build.log | 5 min |
start | After a successful build, on agent boot | /home/node/clawd | /tmp/user-start.log | None - runs detached |
If build fails, start does not run. If start crashes, the agent is still healthy - only the user-defined process exits.
Retry the lifecycle: POST /v0/agents/{agentId}/scripts/retry (or the action on the Danger tab).
Bind servers to 0.0.0.0, not localhost, so the gateway can reach them. See Routes.
routes
Port-forwarding rules. Up to 10. Each entry maps an external path prefix to a container port.
"routes": [
{ "port": 5173, "path": "/app", "protected": false },
{ "port": 3000, "path": "/api", "protected": true }
]
| Field | Type | Notes |
|---|
port | integer | Container port. 1025-65535. 18789 is reserved. |
path | string | URL path prefix. Stripped from the request before reaching your service. |
protected | boolean | true requires a gateway token. Defaults to false. |
For custom domains, register them through the UI or the Domains API - they aren’t declared in manifest.json.
channels
Configures the messaging channels for this agent. Tokens are usually injected from secrets to avoid leaking into the manifest.
"channels": {
"telegram": {
"botToken": "env:TELEGRAM_BOT_TOKEN",
"dmPolicy": "pairing",
"allowFrom": ["123456789"]
},
"slack": {
"botToken": "env:SLACK_BOT_TOKEN",
"appToken": "env:SLACK_APP_TOKEN"
},
"discord": {
"botToken": "env:DISCORD_BOT_TOKEN"
}
}
| Channel | Required fields | Notes |
|---|
telegram | botToken | dmPolicy (open / pairing), allowFrom (user IDs) |
slack | botToken, appToken | Socket Mode + scopes per Channels |
discord | botToken | |
whatsapp | dmPolicy, allowFrom | Linking happens on the agent. Coming soon. |
Use env:VAR_NAME to read from an environment variable instead of embedding a literal token.
template
Only used when the manifest is the source for a marketplace template. Ignored for direct deploys.
"template": {
"slug": "useful-assistant",
"category": "general",
"partnerName": "Pinata",
"tags": ["assistant", "personal", "productivity"]
}
| Field | Notes |
|---|
slug | Marketplace URL slug. Lowercase, hyphens. |
category | One of the marketplace categories (e.g. general, defi, social) |
partnerName | Display name shown on the template card |
tags | Array of free-text tags for filtering |
paid | Optional. Set { "amount": "1.00", "currency": "USDC" } for x402 paid templates |
Validation
To validate manifest.json ahead of committing, run it through the template validator (which checks manifest.json + README.md + workspace/):
# CLI
pinata agents templates validate https://github.com/user/my-template
# Or hit the API directly with the repo URL + ref
curl -X POST \
-H "Authorization: Bearer $PINATA_JWT" \
-H "Content-Type: application/json" \
-d '{"gitUrl":"https://github.com/user/my-template","ref":"refs/heads/main"}' \
https://agents.pinata.cloud/v0/templates/validate
The response is { valid: boolean, errors: string[], manifest, readme, files } — any problems with the manifest show up in the errors array.
Schema constraints to keep in mind while authoring:
| Field | Constraint |
|---|
version | Must be 1 |
agent | Required; agent.name is required and ≤ 100 chars |
agent.description | ≤ 10000 chars |
agent.vibe | ≤ 200 chars |
agent.emoji | ≤ 32 chars |
skills | ≤ 10 entries |
routes | ≤ 10 entries; ports 1025–65535, excluding 18789 |
tasks | ≤ 20 entries; minimum interval 1 minute |
channels.*.botToken | Required on initial setup (Slack also requires appToken) |
See Errors for the full HTTP status code reference.
Minimal Example
The smallest valid manifest:
{
"version": 1,
"agent": { "name": "Hello" }
}
This boots the default openclaw engine with no skills, no scripts, and no routes - just a workspace and a chat interface.