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 ExecutedHow It Works
- Events occur on the board (objects created, participants join, timers tick)
- Agents listen for events matching their trigger configuration
- Conditions filter which events should trigger actions (optional)
- Actions execute when trigger + condition match
- Loop prevention ensures agents don't react to their own actions
Available Events
Agents can subscribe to the following board events:
| Event | Description | Payload Fields |
|---|---|---|
object:created | New object added to board | objectId, objectType, data |
object:updated | Object modified | objectId, objectType, data |
object:deleted | Object removed from board | objectId, objectType |
participant:joined | User joined the session | participantId, userId, data |
participant:left | User left the session | participantId, userId |
participant:idle | User inactive for threshold period | participantId, data.idleSeconds |
frame:entered | Participant entered a frame | frameId, participantId |
frame:left | Participant left a frame | frameId, participantId |
timer:tick | Periodic timer event | data.interval |
schedule:trigger | Scheduled action triggered | data.scheduleId |
Trigger Configuration
Each trigger defines when and how an agent should react to events.
Basic Structure
{
"event": "object:created",
"condition": "object.type === 'sticky-note'",
"action": "evaluate_answer",
"params": {
"criteria": "Check if answer is correct"
},
"allowSelfEvents": false
}Fields
| Field | Type | Required | Description |
|---|---|---|---|
event | string | Yes | Event type to listen for (from table above) |
condition | string | No | JavaScript-like expression to filter events |
action | string | Yes | Action type to execute when triggered |
params | object | No | Parameters passed to the action |
allowSelfEvents | boolean | No | Allow agent to react to its own actions (default: false) |
Multiple Triggers
Agents can have multiple triggers for different scenarios:
{
"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:
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
| Operator | Example | Description |
|---|---|---|
=== | object.type === 'card' | Equality check |
!== | object.status !== 'done' | Inequality check |
> | participant.idleSeconds > 300 | Greater than |
< | object.score < 50 | Less than |
>= | object.count >= 10 | Greater than or equal |
<= | object.count <= 100 | Less than or equal |
&& | object.type === 'card' && object.status === 'pending' | Logical AND |
| ` | ` | |
.includes() | object.text.includes('help') | String/array contains |
Condition Examples
Check object type:
"object.type === 'sticky-note'"Check participant idle time:
"participant.idleSeconds > 180"Multiple conditions (AND):
"object.type === 'answer-card' && object.submitted === true"Multiple conditions (OR):
"object.type === 'sticky-note' || object.type === 'text'"String contains:
"object.text.includes('help')"Numeric comparison:
"object.score >= 80"Complex expression:
"object.type === 'sticky-note' && object.text.includes('question') && participant.id !== event.userId"Available Actions
Actions define what the agent does when triggered.
Action Types
| Action | Description | Required Params |
|---|---|---|
create_object | Add a new object to the board | type, data, position |
update_object | Modify an existing object | objectId, updates |
delete_object | Remove an object from the board | objectId |
move_objects | Move multiple objects | objectIds, deltaX, deltaY |
send_notification | Send a message to users | message, targetUserId (optional) |
move_to_frame | Move participant to a frame | participantId, frameId |
assign_to_room | Assign participant to a room/frame | participantId, frameId |
generate_content | Generate text using AI | prompt, context |
evaluate_answer | Check student answer with AI | objectId, criteria |
generate_hint | Create a hint for a task | targetObjectId, context |
summarize | Create summary of board content | scope, frameId (optional) |
log_event | Log event to agent memory | message, data |
update_memory | Update agent's persistent memory | key, value |
pause_self | Pause the agent | - |
notify_teacher | Send notification to board owner | message, priority |
set_thinking | Show "thinking" indicator | message |
Action Examples
Create a hint sticky note:
{
"action": "generate_hint",
"params": {
"targetObjectId": "task-uuid",
"context": "Student struggling with multiplication"
}
}Send notification to specific user:
{
"action": "send_notification",
"params": {
"message": "Great work on this task!",
"targetUserId": "user-123"
}
}Create a feedback object:
{
"action": "create_object",
"params": {
"type": "sticky-note",
"data": {
"text": "✓ Correct answer!",
"backgroundColor": "#4ade80"
},
"position": {
"x": 100,
"y": 200
}
}
}Evaluate student answer:
{
"action": "evaluate_answer",
"params": {
"objectId": "answer-uuid",
"criteria": "Check if the multiplication result is correct"
}
}Update agent memory:
{
"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).
{
"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:
{
"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:
// Agent with priority=8 processes first
// Lower priority agents skip locked objectsConfigure priority when creating the agent (1-10, default: 5).
Scheduled Actions
Agents can execute actions on a schedule, independent of events.
Schedule Configuration
{
"instructions": {
"schedule": [
{
"at": "every:10min",
"action": "send_notification",
"params": {
"message": "10 minutes remaining!"
}
},
{
"at": "every:5min",
"action": "summarize",
"params": {
"scope": "board"
}
}
]
}
}Schedule Formats
| Format | Example | Description |
|---|---|---|
every:Nmin | every:5min | Repeat every N minutes |
every:Nh | every:1h | Repeat every N hours |
at:HH:MM | at:14:30 | Execute at specific time (session timezone) |
after:Nmin | after:30min | Execute 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:
{
"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
{
"event": "object:created",
"action": "generate_hint"
}✅ Good: Filter by object type
{
"event": "object:created",
"condition": "object.type === 'answer-card'",
"action": "evaluate_answer"
}2. Set Rate Limits
Always configure maxActionsPerMinute to prevent runaway agents:
{
"maxActionsPerMinute": 10 // Max 10 actions per minute
}3. Use Budget Limits for AI Actions
For agents using AI (like evaluate_answer, generate_hint):
{
"budgetTokens": 50000 // Stop after 50k tokens used
}4. Test Conditions Thoroughly
Before deploying, test your conditions with sample data:
// 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:
{
"scope": {
"frames": ["student-zone"],
"objectTypes": ["sticky-note", "text"]
}
}6. Monitor Agent Actions
Check agent execution logs to debug unexpected behavior:
GET /api/v1/boards/{boardUuid}/agents/{agentId}/actionsTroubleshooting
Agent Not Triggering
Check:
- ✅ Agent status is
active(notpaused) - ✅ Event type matches exactly (
object:creatednotobjectCreated) - ✅ 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'notobject.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:
GET /api/v1/boards/{boardUuid}/agents/{agentId}{
"budgetTokens": 50000,
"spentTokens": 50123, // Over budget!
"status": "paused"
}Solution: Increase budget or reset the agent.
Next Steps
- Agent Types & Personas - Pre-configured agent templates
- Agent Management API - Create, update, and control agents
- Memory & Context - How agents remember past interactions
Related Resources
- WebSocket Events - Real-time event reference
- Custom Objects - Define your own object types
- Frames API - Working with board frames