Skip to content

Triggers & Actions Reference

AI Agents use an event-driven architecture to react to board activity in real-time. This guide explains the available events, trigger configuration, and action types.

Event-Driven Architecture

Agents operate on a simple Trigger → Condition → Action flow:

Board Event → Agent Trigger Matches → Condition Evaluated → Action Executed

How It Works

  1. Events occur on the board (objects created, participants join, timers tick)
  2. Agents listen for events matching their trigger configuration
  3. Conditions filter which events should trigger actions (optional)
  4. Actions execute when trigger + condition match
  5. Loop prevention ensures agents don't react to their own actions

Available Events

Agents can subscribe to the following board events:

EventDescriptionPayload Fields
object:createdNew object added to boardobjectId, objectType, data
object:updatedObject modifiedobjectId, objectType, data
object:deletedObject removed from boardobjectId, objectType
participant:joinedUser joined the sessionparticipantId, userId, data
participant:leftUser left the sessionparticipantId, userId
participant:idleUser inactive for threshold periodparticipantId, data.idleSeconds
frame:enteredParticipant entered a frameframeId, participantId
frame:leftParticipant left a frameframeId, participantId
timer:tickPeriodic timer eventdata.interval
schedule:triggerScheduled action triggereddata.scheduleId

Trigger Configuration

Each trigger defines when and how an agent should react to events.

Basic Structure

json
{
  "event": "object:created",
  "condition": "object.type === 'sticky-note'",
  "action": "evaluate_answer",
  "params": {
    "criteria": "Check if answer is correct"
  },
  "allowSelfEvents": false
}

Fields

FieldTypeRequiredDescription
eventstringYesEvent type to listen for (from table above)
conditionstringNoJavaScript-like expression to filter events
actionstringYesAction type to execute when triggered
paramsobjectNoParameters passed to the action
allowSelfEventsbooleanNoAllow agent to react to its own actions (default: false)

Multiple Triggers

Agents can have multiple triggers for different scenarios:

json
{
  "instructions": {
    "triggers": [
      {
        "event": "object:created",
        "condition": "object.type === 'sticky-note'",
        "action": "evaluate_answer"
      },
      {
        "event": "participant:idle",
        "condition": "participant.idleSeconds > 300",
        "action": "send_notification",
        "params": {
          "message": "Are you still working?"
        }
      }
    ]
  }
}

Condition Expressions

Conditions use JavaScript-like syntax to filter events. The agent only acts when the condition evaluates to true.

Available Variables

When evaluating conditions, you have access to:

javascript
object: {
  id: string;
  type: string;
  // ... other fields from event.data
}

participant: {
  id: string;
  // ... other fields from event.data
}

event: {
  type: string;
  userId: string;
  timestamp: string;
}

frame: {
  id: string;
}

Supported Operators

OperatorExampleDescription
===object.type === 'card'Equality check
!==object.status !== 'done'Inequality check
>participant.idleSeconds > 300Greater than
<object.score < 50Less than
>=object.count >= 10Greater than or equal
<=object.count <= 100Less than or equal
&&object.type === 'card' && object.status === 'pending'Logical AND
``
.includes()object.text.includes('help')String/array contains

Condition Examples

Check object type:

javascript
"object.type === 'sticky-note'"

Check participant idle time:

javascript
"participant.idleSeconds > 180"

Multiple conditions (AND):

javascript
"object.type === 'answer-card' && object.submitted === true"

Multiple conditions (OR):

javascript
"object.type === 'sticky-note' || object.type === 'text'"

String contains:

javascript
"object.text.includes('help')"

Numeric comparison:

javascript
"object.score >= 80"

Complex expression:

javascript
"object.type === 'sticky-note' && object.text.includes('question') && participant.id !== event.userId"

Available Actions

Actions define what the agent does when triggered.

Action Types

ActionDescriptionRequired Params
create_objectAdd a new object to the boardtype, data, position
update_objectModify an existing objectobjectId, updates
delete_objectRemove an object from the boardobjectId
move_objectsMove multiple objectsobjectIds, deltaX, deltaY
send_notificationSend a message to usersmessage, targetUserId (optional)
move_to_frameMove participant to a frameparticipantId, frameId
assign_to_roomAssign participant to a room/frameparticipantId, frameId
generate_contentGenerate text using AIprompt, context
evaluate_answerCheck student answer with AIobjectId, criteria
generate_hintCreate a hint for a tasktargetObjectId, context
summarizeCreate summary of board contentscope, frameId (optional)
log_eventLog event to agent memorymessage, data
update_memoryUpdate agent's persistent memorykey, value
pause_selfPause the agent-
notify_teacherSend notification to board ownermessage, priority
set_thinkingShow "thinking" indicatormessage

Action Examples

Create a hint sticky note:

json
{
  "action": "generate_hint",
  "params": {
    "targetObjectId": "task-uuid",
    "context": "Student struggling with multiplication"
  }
}

Send notification to specific user:

json
{
  "action": "send_notification",
  "params": {
    "message": "Great work on this task!",
    "targetUserId": "user-123"
  }
}

Create a feedback object:

json
{
  "action": "create_object",
  "params": {
    "type": "sticky-note",
    "data": {
      "text": "✓ Correct answer!",
      "backgroundColor": "#4ade80"
    },
    "position": {
      "x": 100,
      "y": 200
    }
  }
}

Evaluate student answer:

json
{
  "action": "evaluate_answer",
  "params": {
    "objectId": "answer-uuid",
    "criteria": "Check if the multiplication result is correct"
  }
}

Update agent memory:

json
{
  "action": "update_memory",
  "params": {
    "key": "hintsGiven",
    "value": 3
  }
}

Preventing Infinite Loops

Agents can create infinite loops if they react to their own actions. The platform provides two mechanisms to prevent this:

1. Default Self-Filter

By default, agents ignore events they created (allowSelfEvents: false).

json
{
  "event": "object:created",
  "action": "generate_hint",
  "allowSelfEvents": false  // Default behavior
}

This agent will NOT trigger when it creates its own hint objects.

2. Allow Self-Events (Advanced)

In rare cases, you may want an agent to react to its own actions. Set allowSelfEvents: true:

json
{
  "event": "object:created",
  "condition": "object.type === 'counter' && object.count < 10",
  "action": "update_object",
  "params": {
    "updates": {
      "count": "{{object.count + 1}}"
    }
  },
  "allowSelfEvents": true  // ⚠️ Use with caution!
}

Warning: Always include a terminating condition (like count < 10) to prevent infinite loops.

3. Priority-Based Object Locking

When multiple agents target the same object, higher-priority agents lock the object:

javascript
// Agent with priority=8 processes first
// Lower priority agents skip locked objects

Configure priority when creating the agent (1-10, default: 5).

Scheduled Actions

Agents can execute actions on a schedule, independent of events.

Schedule Configuration

json
{
  "instructions": {
    "schedule": [
      {
        "at": "every:10min",
        "action": "send_notification",
        "params": {
          "message": "10 minutes remaining!"
        }
      },
      {
        "at": "every:5min",
        "action": "summarize",
        "params": {
          "scope": "board"
        }
      }
    ]
  }
}

Schedule Formats

FormatExampleDescription
every:Nminevery:5minRepeat every N minutes
every:Nhevery:1hRepeat every N hours
at:HH:MMat:14:30Execute at specific time (session timezone)
after:Nminafter:30minExecute N minutes after agent created

Note: Scheduled actions only run while the agent is active. They pause when the agent is paused.

Complete Example

Here's a complete agent configuration using triggers, conditions, actions, and schedules:

json
{
  "name": "Math Tutor Assistant",
  "persona": "tutor",
  "instructions": {
    "description": "Helps students with math problems and provides hints",
    "goals": [
      "Encourage student thinking",
      "Provide helpful hints without giving answers",
      "Monitor student progress"
    ],
    "rules": [
      "Never provide direct answers",
      "Always be encouraging",
      "Give hints only after student tries"
    ],
    "triggers": [
      {
        "event": "object:created",
        "condition": "object.type === 'answer-card'",
        "action": "evaluate_answer",
        "params": {
          "criteria": "Check if multiplication is correct"
        }
      },
      {
        "event": "participant:idle",
        "condition": "participant.idleSeconds > 120",
        "action": "send_notification",
        "params": {
          "message": "Need any help? I'm here if you need a hint!"
        }
      }
    ],
    "schedule": [
      {
        "at": "every:10min",
        "action": "notify_teacher",
        "params": {
          "message": "Progress update",
          "priority": "low"
        }
      }
    ]
  },
  "scope": {
    "frames": ["math-zone"],
    "objectTypes": ["sticky-note", "answer-card"]
  },
  "maxActionsPerMinute": 10,
  "budgetTokens": 50000,
  "priority": 5
}

Best Practices

1. Use Specific Conditions

Bad: Trigger on all object creations

json
{
  "event": "object:created",
  "action": "generate_hint"
}

Good: Filter by object type

json
{
  "event": "object:created",
  "condition": "object.type === 'answer-card'",
  "action": "evaluate_answer"
}

2. Set Rate Limits

Always configure maxActionsPerMinute to prevent runaway agents:

json
{
  "maxActionsPerMinute": 10  // Max 10 actions per minute
}

3. Use Budget Limits for AI Actions

For agents using AI (like evaluate_answer, generate_hint):

json
{
  "budgetTokens": 50000  // Stop after 50k tokens used
}

4. Test Conditions Thoroughly

Before deploying, test your conditions with sample data:

javascript
// Will this match what you expect?
"object.type === 'sticky-note' && object.text.includes('help')"

5. Use Scopes to Limit Agent Reach

Restrict agents to specific frames or object types:

json
{
  "scope": {
    "frames": ["student-zone"],
    "objectTypes": ["sticky-note", "text"]
  }
}

6. Monitor Agent Actions

Check agent execution logs to debug unexpected behavior:

http
GET /api/v1/boards/{boardUuid}/agents/{agentId}/actions

Troubleshooting

Agent Not Triggering

Check:

  • ✅ Agent status is active (not paused)
  • ✅ Event type matches exactly (object:created not objectCreated)
  • ✅ Condition syntax is correct
  • ✅ Agent scope includes the target frame/object type
  • ✅ Not hitting rate limits (maxActionsPerMinute)

Agent Triggering Too Often

Solutions:

  • Add more specific conditions
  • Reduce trigger scope (scope.frames, scope.objectTypes)
  • Lower maxActionsPerMinute
  • Use allowSelfEvents: false (default)

Condition Not Evaluating

Common issues:

  • String comparison needs quotes: object.type === 'card' not object.type === card
  • Case sensitivity matters: 'Card''card'
  • Check field names match event payload exactly

Budget Exhausted

When AI token budget runs out, the agent pauses automatically. Check:

http
GET /api/v1/boards/{boardUuid}/agents/{agentId}
json
{
  "budgetTokens": 50000,
  "spentTokens": 50123,  // Over budget!
  "status": "paused"
}

Solution: Increase budget or reset the agent.

Next Steps