Skills Format Specification

The skills.md format defines how Skills are structured, configured, and executed. This specification ensures consistent behavior across all Tajo Skills.

File Structure

A skill is defined in a single markdown file with YAML frontmatter:

---
name: customer-sync
version: 2.1.0
description: Sync customer data to Brevo contacts
category: data-sync
status: stable
triggers:
- event: customer_created
- event: customer_updated
- event: customer_deleted
actions:
- brevo/create-contact
- brevo/update-contact
- brevo/delete-contact
brevoEndpoints:
- POST /v3/contacts
- PUT /v3/contacts/{identifier}
- DELETE /v3/contacts/{identifier}
permissions:
- contacts:write
- contacts:read
---
# Customer Sync
Automatically synchronize customer data from your platform to Brevo contacts.
## Overview
This skill listens for customer lifecycle events and mirrors changes to Brevo...

Frontmatter Fields

Required Fields

FieldTypeDescription
namestringUnique identifier (kebab-case)
versionstringSemantic version (e.g., “2.1.0”)
descriptionstringShort description (max 160 chars)
categoryenumOne of: data-sync, email-marketing, sms-whatsapp, loyalty, analytics, integrations
triggersarrayEvents that activate this skill
actionsarrayOperations this skill can perform

Optional Fields

FieldTypeDefaultDescription
statusenumstableOne of: stable, beta, experimental
brevoEndpointsarray[]Brevo API endpoints used
permissionsarray[]Required Brevo API permissions
relatedSkillsarray[]IDs of related skills
featuredbooleanfalseHighlight in skill catalog

Triggers

Triggers define what events activate the skill.

Event Triggers

triggers:
- event: cart_abandoned
conditions:
- cart_value: "> 50" # Minimum cart value
- items_count: ">= 1" # At least one item
- time_since_activity: "> 30m" # 30 minutes of inactivity
debounce: 5m # Wait 5 minutes before re-triggering

Schedule Triggers

triggers:
- schedule: "0 9 * * *" # Cron expression (daily at 9am)
timezone: "America/New_York"
- schedule: every_hour
- schedule: every_day

Webhook Triggers

triggers:
- webhook: /skills/customer-sync/trigger
method: POST
authentication: api_key

Condition Operators

OperatorDescriptionExample
=Equalsstatus: "active"
!=Not equalsstatus: "!= deleted"
>Greater thancart_value: "> 50"
>=Greater than or equalitems: ">= 1"
<Less thanage: "< 30"
<=Less than or equalquantity: "<= 10"
containsString containsemail: "contains @gmail.com"
starts_withString prefixname: "starts_with Dr."
inValue in listcountry: "in US,CA,UK"

Actions

Actions define what operations the skill performs.

Action Definition

actions:
- id: send_reminder_email
type: brevo/send-email
parameters:
template_id: 12345
to: "{{ contact.email }}"
params:
first_name: "{{ contact.firstName }}"
cart_items: "{{ cart.items }}"
retry:
attempts: 3
backoff: exponential
on_error: continue # or 'stop'

Action Types

TypeDescription
brevo/send-emailSend transactional email
brevo/send-smsSend SMS message
brevo/send-whatsappSend WhatsApp message
brevo/create-contactCreate new contact
brevo/update-contactUpdate contact attributes
brevo/delete-contactDelete contact
brevo/add-to-listAdd contact to list
brevo/remove-from-listRemove contact from list
brevo/track-eventTrack custom event
http/requestMake HTTP request
transform/mapTransform data
control/delayWait before continuing
control/conditionBranch based on condition

Template Variables

Use {{ }} syntax to reference data:

parameters:
to: "{{ contact.email }}"
subject: "Your order #{{ order.number }} has shipped"
params:
name: "{{ contact.firstName | default: 'Customer' }}"
items: "{{ cart.items | map: 'name' | join: ', ' }}"
total: "{{ cart.total | currency: 'USD' }}"

Available Filters

FilterDescriptionExample
defaultDefault value{{ name | default: 'Guest' }}
uppercaseUppercase string{{ name | uppercase }}
lowercaseLowercase string{{ email | lowercase }}
capitalizeCapitalize first letter{{ name | capitalize }}
truncateTruncate string{{ desc | truncate: 100 }}
dateFormat date{{ date | date: 'YYYY-MM-DD' }}
currencyFormat currency{{ price | currency: 'EUR' }}
mapMap array property{{ items | map: 'name' }}
joinJoin array{{ tags | join: ', ' }}
firstFirst array item{{ items | first }}
lastLast array item{{ items | last }}
sizeArray/string length{{ items | size }}

Permissions

Define required Brevo API permissions:

permissions:
- contacts:read # Read contact data
- contacts:write # Create/update contacts
- email:send # Send transactional emails
- sms:send # Send SMS messages
- lists:write # Manage contact lists
- events:write # Track events

Complete Example

---
name: abandoned-cart-recovery
version: 3.0.0
description: Recover abandoned shopping carts with a multi-step email sequence
category: email-marketing
status: stable
triggers:
- event: cart_abandoned
conditions:
- cart_value: "> 25"
- customer_email: "exists"
- items_count: ">= 1"
debounce: 30m
actions:
- id: wait_1h
type: control/delay
parameters:
duration: 1h
- id: check_purchase
type: control/condition
parameters:
condition: "{{ cart.converted }} = false"
then: send_first_email
else: stop
- id: send_first_email
type: brevo/send-email
parameters:
template_id: {{ env.ABANDONED_CART_TEMPLATE_1 }}
to: "{{ contact.email }}"
params:
first_name: "{{ contact.firstName }}"
cart_url: "{{ cart.recovery_url }}"
items: "{{ cart.items }}"
total: "{{ cart.total | currency }}"
- id: wait_24h
type: control/delay
parameters:
duration: 24h
- id: check_purchase_2
type: control/condition
parameters:
condition: "{{ cart.converted }} = false"
then: send_second_email
else: stop
- id: send_second_email
type: brevo/send-email
parameters:
template_id: {{ env.ABANDONED_CART_TEMPLATE_2 }}
to: "{{ contact.email }}"
params:
first_name: "{{ contact.firstName }}"
cart_url: "{{ cart.recovery_url }}"
discount_code: "{{ generate_discount(10, 'percent') }}"
brevoEndpoints:
- POST /v3/smtp/email
- GET /v3/contacts/{identifier}
permissions:
- contacts:read
- email:send
relatedSkills:
- customer-sync
- order-events
- browse-abandonment
---
# Abandoned Cart Recovery
Recover lost sales with a proven multi-step email sequence...

MCP Tool Exposure

Skills can be exposed as MCP tools, making them callable by AI agents. Add the mcp field to your frontmatter:

---
name: abandoned-cart-recovery
version: 3.0.0
description: Recover abandoned shopping carts with a multi-step email sequence
category: email-marketing
# MCP Configuration
mcp:
tool_name: tajo/recover-abandoned-cart
description: Execute abandoned cart recovery sequence for a specific cart
inputSchema:
type: object
properties:
cart_id:
type: string
description: The abandoned cart identifier
customer_email:
type: string
description: Customer email address
min_cart_value:
type: number
description: Minimum cart value to trigger recovery
default: 25
required: [cart_id, customer_email]
brevo_servers:
- brevo_contacts
- brevo_email_campaign_management
- brevo_templates
---

How MCP Exposure Works

When a skill has an mcp field, it becomes a tool that AI agents can discover and invoke:

Agent: "Recover abandoned cart #4521 for [email protected]"
MCP Tool Discovery: finds tajo/recover-abandoned-cart
Tool Execution: runs the skill's action chain
Brevo MCP Servers: contacts + email modules called
Result: recovery sequence initiated

MCP Fields

FieldTypeDescription
mcp.tool_namestringMCP tool name (format: tajo/skill-name)
mcp.descriptionstringDescription shown to AI agents during tool discovery
mcp.inputSchemaobjectJSON Schema defining the tool’s input parameters
mcp.brevo_serversarrayWhich Brevo MCP server modules this skill needs

Skills vs Direct MCP Tools

AspectSkill as MCP ToolDirect Brevo MCP
AbstractionHigh, agent says “recover this cart”Low, agent must call individual Brevo endpoints
ComplexityEncapsulates multi-step logicAgent must orchestrate each step
GuardrailsBuilt into the skill (conditions, debounce)Agent must implement its own
Best forRepeatable workflowsAd-hoc operations

Tip

Use Skills as MCP tools for complex, multi-step workflows that agents shouldn’t reinvent each time. Use direct Brevo MCP tools for simple, one-off operations like looking up a contact or sending a single email.

Composing Skills and Agents

An agent can use both Skills (as MCP tools) and direct Brevo MCP modules:

# Agent spec
---
name: retention-agent
tools:
# Tajo Skills as MCP tools
- tajo/recover-abandoned-cart
- tajo/customer-sync
- tajo/win-back-sequence
# Direct Brevo MCP modules
- brevo_contacts
- brevo_campaign_analytics
- brevo_segments
---

This gives agents high-level automation (Skills) for common patterns while retaining low-level access (Brevo MCP) for custom logic.

See Agent Specification Format and Building Agents for full details.

Best Practices

Tip

Version your skills using semantic versioning. Breaking changes require a major version bump.

  1. Keep skills focused - One skill should do one thing well
  2. Use descriptive names - abandoned-cart-recovery not acr
  3. Document conditions - Explain why each condition exists
  4. Handle errors gracefully - Use on_error: continue for non-critical actions
  5. Test with small audiences - Use status: experimental during development
  6. Add MCP exposure for skills that agents should be able to invoke directly

Next Steps

Subscribe to updates

developer-docs

Drop your email or phone number — we'll send you what matters next.

auto-detect
AI Assistant

Hi! Ask me anything about the docs.