Manifests API
The Manifests API provides endpoints for managing team manifests - declarative configurations that define composable AI teams with versioned components.
Overview
Team manifests follow the "npm for AI agents" paradigm. They allow you to:
- Validate manifest syntax before deploying
- Resolve component versions without deploying (dry run)
- Deploy teams from manifests
- Upgrade components to newer versions
- Rollback to previous versions
- Export current team state as manifest
Endpoints Summary
| Method | Endpoint | Description |
|---|---|---|
| POST | /manifests/validate | Validate manifest syntax |
| POST | /manifests/resolve | Resolve versions (dry run) |
| POST | /manifests/deploy | Deploy team from manifest |
| GET | /manifests | List all deployments |
| GET | /manifests/:deployId | Get deployment details |
| GET | /manifests/:deployId/export | Export as manifest |
| POST | /manifests/:deployId/upgrade | Upgrade components |
| POST | /manifests/:deployId/rollback | Rollback component |
| GET | /manifests/deployments | List deployments |
| GET | /manifests/deployments/:teamSlug | Get deployment by slug |
| GET | /manifests/deployments/:teamSlug/manifest | Export manifest |
| GET | /manifests/deployments/:teamSlug/lockfile | Export lock file |
| POST | /manifests/deployments/:teamSlug/upgrade | Upgrade deployment |
| POST | /manifests/components/:type/:id/rollback | Rollback component |
Validation
Validate Manifest
Validate a manifest without deploying. Returns syntax errors and warnings.
POST /api/manifests/validate
Content-Type: application/json
Authorization: Bearer <token>
{
"manifest": {
"$schema": "https://meetloyd.com/schemas/team.manifest.json",
"name": "My Team",
"slug": "my-team",
"version": "1.0.0",
"components": {
"agents": [
{
"ref": "store://agents/sdr-agent",
"version": "^1.0.0",
"localId": "sdr"
}
]
}
}
}
Response (valid):
{
"valid": true,
"errors": [],
"warnings": []
}
Response (invalid):
{
"valid": false,
"errors": [
{
"path": "components.agents[0].ref",
"message": "Invalid component reference format"
}
],
"warnings": [
{
"path": "version",
"message": "Using caret version range allows minor updates"
}
]
}
Resolution
Resolve Manifest (Dry Run)
Resolve all component versions without deploying. Returns what the lock file would look like.
POST /api/manifests/resolve
Content-Type: application/json
Authorization: Bearer <token>
{
"manifest": {
"name": "Sales Team",
"slug": "sales-team",
"version": "1.0.0",
"components": {
"agents": [
{
"ref": "store://agents/sdr-agent",
"version": "^1.0.0",
"localId": "sdr"
}
],
"skills": [
{
"ref": "store://skills/salesforce-crm",
"version": "^3.0.0"
}
]
}
}
}
Response:
{
"success": true,
"lockFile": {
"manifestVersion": "1.0.0",
"resolvedAt": "2026-01-15T10:30:00Z",
"checksum": "sha256:abc123...",
"components": {
"agents": {
"store://agents/sdr-agent": {
"ref": "store://agents/sdr-agent",
"resolvedVersion": "1.2.3",
"configHash": "sha256:def456..."
}
},
"skills": {
"store://skills/salesforce-crm": {
"ref": "store://skills/salesforce-crm",
"resolvedVersion": "3.1.2",
"configHash": "sha256:ghi789..."
}
}
}
},
"errors": [],
"warnings": []
}
Response (resolution failed):
{
"success": false,
"lockFile": null,
"errors": [
{
"component": "store://agents/unknown-agent",
"message": "Component not found in store"
}
],
"warnings": []
}
Deployment
Deploy Team from Manifest
Deploy a complete team from a manifest configuration.
POST /api/manifests/deploy
Content-Type: application/json
Authorization: Bearer <token>
{
"manifest": {
"name": "Enterprise Sales",
"slug": "enterprise-sales",
"version": "2.0.0",
"description": "AI-powered enterprise sales team",
"components": {
"agents": [
{
"ref": "store://agents/sdr-agent",
"version": "1.2.3",
"locked": true,
"localId": "sdr"
},
{
"ref": "store://agents/ae-agent",
"version": "^1.0.0",
"localId": "ae",
"customizations": {
"contextPromptTemplate": "You specialize in {{industry}} sales."
}
}
],
"skills": [
{
"ref": "store://skills/salesforce-crm",
"version": "3.1.2",
"locked": true
}
],
"avatars": [
{
"ref": "external://heygen/professional-sarah",
"localId": "sarah"
}
]
},
"orchestration": {
"mode": "hierarchical",
"entryAgentId": "sdr",
"routing": {
"intentRouting": [
{
"intent": "pricing_inquiry",
"targetAgentId": "ae",
"priority": 1
}
],
"fallbackAgentId": "sdr"
}
}
},
"options": {
"dryRun": false,
"force": false,
"notes": "Initial deployment for Q1 sales push"
}
}
Options:
| Option | Type | Default | Description |
|---|---|---|---|
dryRun | boolean | false | Simulate deployment without changes |
force | boolean | false | Override existing deployment |
skipResolution | boolean | false | Skip version resolution |
notes | string | - | Deployment notes for audit |
Response:
{
"success": true,
"deployment": {
"id": "deploy_abc123",
"teamSlug": "enterprise-sales",
"teamVersion": "2.0.0",
"status": "active",
"deployedAt": "2026-01-15T10:30:00Z"
},
"createdAgents": [
{ "id": "agent_sdr123", "localId": "sdr", "name": "SDR Agent" },
{ "id": "agent_ae456", "localId": "ae", "name": "AE Agent" }
],
"createdSkills": [
{ "id": "skill_sf789", "name": "Salesforce CRM" }
],
"createdAvatars": [
{ "id": "avatar_sarah", "localId": "sarah", "provider": "heygen" }
]
}
Response (failed):
{
"success": false,
"errors": [
{
"code": "COMPONENT_NOT_FOUND",
"message": "Agent store://agents/unknown not found"
}
],
"resolution": null
}
Deployment Management
List Deployments
Get all team deployments for your tenant.
GET /api/manifests
Authorization: Bearer <token>
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 50 | Max results (1-100) |
offset | integer | 0 | Pagination offset |
status | string | - | Filter by status |
Response:
{
"deploys": [
{
"id": "deploy_abc123",
"tenantId": "tenant_xyz",
"teamSlug": "enterprise-sales",
"teamVersion": "2.0.0",
"status": "active",
"deployedAt": "2026-01-15T10:30:00Z",
"deployedBy": "user_123",
"lastResolvedAt": "2026-01-15T10:30:00Z",
"componentCount": 4,
"hasUpdates": true
}
],
"total": 1
}
Get Deployment Details
Get full details of a specific deployment.
GET /api/manifests/:deployId
Authorization: Bearer <token>
Response:
{
"manifest": {
"name": "Enterprise Sales",
"slug": "enterprise-sales",
"version": "2.0.0",
"components": { ... }
},
"lockFile": {
"manifestVersion": "2.0.0",
"resolvedAt": "2026-01-15T10:30:00Z",
"components": [
{
"id": "store://agents/sdr-agent",
"type": "agent",
"ref": "store://agents/sdr-agent",
"resolvedVersion": "1.2.3",
"checksum": "sha256:abc123...",
"config": {},
"locked": true
},
{
"id": "store://skills/salesforce-crm",
"type": "skill",
"ref": "store://skills/salesforce-crm",
"resolvedVersion": "3.1.2",
"checksum": "sha256:def456...",
"config": {},
"locked": true
}
]
},
"status": "active"
}
Get Deployment by Team Slug
Alternative endpoint using team slug instead of deployment ID.
GET /api/manifests/deployments/:teamSlug
Authorization: Bearer <token>
Response:
{
"id": "deploy_abc123",
"teamSlug": "enterprise-sales",
"teamVersion": "2.0.0",
"status": "active",
"deployedAt": "2026-01-15T10:30:00Z",
"deployedBy": "user_123",
"lastResolvedAt": "2026-01-15T10:30:00Z",
"notes": "Initial deployment",
"manifest": { ... },
"lockFile": { ... }
}
Export
Export Manifest
Export the current deployment state as a manifest file.
GET /api/manifests/:deployId/export
Authorization: Bearer <token>
Response:
{
"manifest": {
"$schema": "https://meetloyd.com/schemas/team.manifest.json",
"name": "Enterprise Sales",
"slug": "enterprise-sales",
"version": "2.0.0",
"exportedAt": "2026-01-15T12:00:00Z",
"components": {
"agents": [
{
"ref": "store://agents/sdr-agent",
"version": "1.2.3",
"locked": true,
"localId": "sdr"
}
],
"skills": [
{
"ref": "store://skills/salesforce-crm",
"version": "3.1.2",
"locked": true
}
]
},
"orchestration": { ... }
}
}
Export Lock File
Export the lock file with resolved versions.
GET /api/manifests/deployments/:teamSlug/lockfile
Authorization: Bearer <token>
Response:
{
"manifestVersion": "2.0.0",
"resolvedAt": "2026-01-15T10:30:00Z",
"checksum": "sha256:abc123...",
"components": {
"agents": {
"store://agents/sdr-agent": {
"ref": "store://agents/sdr-agent",
"resolvedVersion": "1.2.3",
"configHash": "sha256:def456...",
"locked": true
}
},
"skills": { ... },
"avatars": { ... }
}
}
Upgrade
Upgrade Components
Upgrade specific components or all components to newer versions.
POST /api/manifests/:deployId/upgrade
Content-Type: application/json
Authorization: Bearer <token>
{
"componentIds": [
"store://agents/sdr-agent",
"store://skills/salesforce-crm"
],
"dryRun": false
}
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
componentIds | string[] | No | Specific components to upgrade (all if omitted) |
dryRun | boolean | No | Preview changes without applying |
Response:
{
"upgraded": [
"store://agents/sdr-agent",
"store://skills/salesforce-crm"
],
"lockFile": {
"manifestVersion": "2.0.0",
"resolvedAt": "2026-01-15T14:00:00Z",
"components": { ... }
}
}
Upgrade Deployment by Slug
Alternative endpoint using team slug.
POST /api/manifests/deployments/:teamSlug/upgrade
Content-Type: application/json
Authorization: Bearer <token>
{
"components": ["store://agents/sdr-agent"],
"targetVersion": "2.0.0",
"allowBreaking": false,
"dryRun": true
}
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
components | string[] | No | Components to upgrade |
targetVersion | string | No | Target version constraint |
allowBreaking | boolean | No | Allow major version upgrades |
dryRun | boolean | No | Preview only |
Response:
{
"success": true,
"upgrades": [
{
"ref": "store://agents/sdr-agent",
"fromVersion": "1.2.3",
"toVersion": "1.3.0",
"breaking": false,
"changelog": "Added LinkedIn integration"
}
]
}
Rollback
Rollback Component
Rollback a component to a previous version.
POST /api/manifests/:deployId/rollback
Content-Type: application/json
Authorization: Bearer <token>
{
"componentId": "store://agents/sdr-agent",
"toVersion": 2
}
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
componentId | string | Yes | Component reference to rollback |
toVersion | integer | Yes | Target version number |
Response:
{
"success": true
}
Rollback by Component Type
Rollback using component type and ID.
POST /api/manifests/components/:componentType/:componentId/rollback
Content-Type: application/json
Authorization: Bearer <token>
{
"toDeploymentId": "deploy_abc123",
"toVersion": 2
}
Path Parameters:
| Parameter | Description |
|---|---|
componentType | One of: agent, skill, avatar |
componentId | Component identifier |
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
toDeploymentId | string | No | Target deployment ID |
toVersion | integer | No | Target version number |
Response:
{
"success": true,
"component": {
"id": "agent_sdr123",
"type": "agent",
"ref": "store://agents/sdr-agent"
},
"fromVersion": 3,
"toVersion": 2
}
Component References
Component references use URIs to specify sources:
Store References
store://agents/sdr-agent@^1.0.0
store://skills/salesforce-crm@~3.1.0
store://avatars/professional-emma@1.0.0
Version Specifiers:
| Specifier | Example | Matches |
|---|---|---|
| Exact | 1.2.3 | Only 1.2.3 |
| Caret | ^1.0.0 | 1.x.x (minor/patch) |
| Tilde | ~1.2.0 | 1.2.x (patch only) |
Local References
local://agents/my-custom-agent
local://skills/internal-crm
For custom components in your tenant.
External References
external://heygen/avatar-emma-professional
external://elevenlabs/voice-rachel
For third-party avatar and voice providers.
Error Codes
| Code | Description |
|---|---|
INVALID_MANIFEST | Manifest syntax is invalid |
COMPONENT_NOT_FOUND | Referenced component doesn't exist |
VERSION_NOT_SATISFIABLE | No version matches constraint |
DEPLOYMENT_EXISTS | Team already deployed (use force) |
RESOLUTION_FAILED | Could not resolve all components |
ROLLBACK_FAILED | Target version not available |
LOCKED_COMPONENT | Cannot upgrade locked component |
Webhooks
Subscribe to manifest events:
{
"url": "https://your-app.com/webhooks",
"events": [
"manifest.deployed",
"manifest.upgraded",
"manifest.rollback",
"component.update_available"
]
}
Event Payloads:
manifest.deployed
{
"event": "manifest.deployed",
"timestamp": "2026-01-15T10:30:00Z",
"data": {
"deploymentId": "deploy_abc123",
"teamSlug": "enterprise-sales",
"teamVersion": "2.0.0",
"deployedBy": "user_123"
}
}
component.update_available
{
"event": "component.update_available",
"timestamp": "2026-01-15T10:30:00Z",
"data": {
"componentRef": "store://agents/sdr-agent",
"currentVersion": "1.2.3",
"availableVersion": "1.3.0",
"breaking": false
}
}
SDK Examples
TypeScript
import { MeetLoyd } from '@meetloyd/sdk'
const client = new MeetLoyd({ apiKey: 'YOUR_API_KEY' })
// Validate manifest
const validation = await client.manifests.validate({
manifest: myManifest
})
if (!validation.valid) {
console.error('Errors:', validation.errors)
}
// Deploy
const deployment = await client.manifests.deploy({
manifest: myManifest,
options: { notes: 'Q1 deployment' }
})
console.log('Deployed:', deployment.deployment.id)
// Upgrade
await client.manifests.upgrade(deployment.deployment.id, {
componentIds: ['store://agents/sdr-agent']
})
// Rollback
await client.manifests.rollback(deployment.deployment.id, {
componentId: 'store://agents/sdr-agent',
toVersion: 2
})
CLI
# Validate
loyd manifest validate team.manifest.json
# Resolve (dry run)
loyd manifest resolve team.manifest.json
# Deploy
loyd manifest deploy team.manifest.json --notes "Q1 deployment"
# List deployments
loyd manifest list
# Upgrade
loyd manifest upgrade deploy_abc123 --component store://agents/sdr-agent
# Rollback
loyd manifest rollback deploy_abc123 \
--component store://agents/sdr-agent \
--to-version 2
# Export
loyd manifest export deploy_abc123 > team.manifest.json
Deployment Features
Model Alias Resolution
Agent model fields accept human-friendly aliases that are automatically resolved to concrete model IDs at deploy-time:
agents:
- slug: my-agent
model: claude-sonnet-latest # Resolved to claude-sonnet-4-20250514
Available aliases: claude-opus-latest, claude-sonnet-latest, claude-haiku-latest, gpt-latest, gpt-mini-latest, gemini-latest, gemini-flash-latest, mistral-latest, deepseek-latest, llama-latest.
Aliases are resolved during deployment. The runtime executor also resolves aliases as a safety net for agents not deployed through manifests.
Authorization Grants
Agents can declare OpenFGA authorization tuples in manifests. These are provisioned at deploy-time:
agents:
- slug: crm-agent
authorization:
- resource: "crm_object_type:hubspot/contacts"
relation: editor
- resource: "git_repository:github/acme/docs"
relation: reader
Each grant creates an OpenFGA tuple: user: "agent:{id}", relation: "{relation}", object: "{resource}".
Authorization provisioning is non-fatal — if OpenFGA is unavailable, deployment continues with a warning logged.
SPIFFE Identity
Agents deployed via manifests automatically receive a SPIFFE ID (spiffe://meetloyd.com/tenant/{tenantId}/agent/{agentId}). Optional SVID configuration:
agents:
- slug: api-agent
identity:
spiffe:
audiences: ["https://partner-api.example.com"]
svidTTL: 7200
The SPIFFE ID is stored on the agent record. Identity config (audiences, TTL) is stored in orchestrationConfig.identity.
Catalog Validation
All catalog YAML manifests are validated against Zod schemas on load. Validation is warn-only — errors are logged but do not block startup or deployment. Validated schemas include:
| Schema | Validates |
|---|---|
CatalogManifestSchema | Full manifest structure |
CatalogAgentSchema | Agent definitions |
CatalogOrchestrationSchema | Orchestration config |
CatalogInteractionRuleSchema | Interaction rules |
AuthorizationGrantSchema | Authorization grants |
AgentIdentitySchema | SPIFFE identity config |
Programmatic validation:
import { validateCatalogManifest } from '@meetloyd/manifests'
const result = validateCatalogManifest(rawYaml, 'my-team.yaml')
// { valid: boolean, errors: [...], warnings: [...] }
See Also
- Team Manifests Guide - Manifest format reference
- Composing Teams - Practical guide
- Avatar Providers - External avatar config
- Store Overview - Browse and install components
- Agent Authorization - OpenFGA authorization details
- Agent Identity - SPIFFE identity system