Skip to content

Nodes

Nodes are the building blocks of Moira workflows. Each node represents a step in the process with specific behavior defined by its type.

Moira supports 7 interactive node types and 3 automatic node types:

Start

Entry point for workflow execution.

End

Terminal node marking workflow completion.

Agent Directive

Agent task with directive and completion condition.

Condition

Branch execution based on structured conditions.

Expression

Compute values using arithmetic expressions.

Subgraph

Delegate to another workflow.

Telegram Notification

Send notifications via Telegram.

Entry point for workflow execution. Every workflow must have exactly one start node.

{
"id": "start",
"type": "start",
"initialData": {
"projectName": "my-project"
},
"connections": {
"default": "first-task"
}
}
PropertyRequiredDescription
idYesConvention: should be “start”
typeYesMust be "start"
initialDataNoInitial context variables
connections.defaultYesNext node ID

Terminal node marking workflow completion. No outgoing connections.

{
"id": "end",
"type": "end",
"finalOutput": ["result", "summary"]
}
PropertyRequiredDescription
idYesConvention: should be “end”
typeYesMust be "end"
finalOutputNoContext keys to include in final result

The primary node type for agent tasks. Contains a directive (what to do) and completion condition (when done).

{
"id": "analyze-requirements",
"type": "agent-directive",
"directive": "Analyze the requirements document and identify key features",
"completionCondition": "Features are listed with priorities",
"inputSchema": {
"type": "object",
"properties": {
"features": {
"type": "array",
"items": { "type": "string" }
}
},
"required": ["features"]
},
"connections": {
"success": "next-step"
}
}
PropertyRequiredDescription
directiveYesWhat the agent should do
completionConditionYesWhen the step is complete
inputSchemaNoJSON Schema for response validation
maxRetriesNoMax validation retries (default: 3)
retryMessageNoCustom retry message
connections.successYesNext node on success
connections.errorNoNext node on error
connections.maxRetriesExceededNoNext node when retries exhausted

Branch execution based on structured conditions:

{
"id": "check-result",
"type": "condition",
"condition": {
"operator": "eq",
"left": { "contextPath": "status" },
"right": "success"
},
"connections": {
"true": "success-path",
"false": "retry-step"
}
}
PropertyRequiredDescription
conditionYesStructured condition object
connections.trueYesNext node when condition is true
connections.falseYesNext node when condition is false

Conditions use a structured format (not string evaluation):

{
"operator": "and",
"conditions": [
{
"operator": "gt",
"left": { "contextPath": "score" },
"right": 80
},
{
"operator": "eq",
"left": { "contextPath": "validated" },
"right": true
}
]
}

Supported condition types:

  • equals, notEquals
  • greaterThan, lessThan, greaterThanOrEquals, lessThanOrEquals
  • and, or, not
  • exists, isEmpty

Compute values using arithmetic expressions. Useful for counters, calculations, and variable transformations:

{
"id": "increment-counter",
"type": "expression",
"expressions": ["counter = counter + 1", "result = counter * multiplier"],
"connections": {
"default": "next-step",
"error": "error-handler"
}
}
PropertyRequiredDescription
expressionsYesArray of assignment expressions
connections.defaultYesNext node after successful evaluation
connections.errorNoNext node on evaluation error

Expressions support basic arithmetic operations:

  • Arithmetic: +, -, *, /
  • Parentheses: (a + b) * c
  • Assignment: result = a + b
  • Context paths: step.index, plan.items[0].value
{
"expressions": ["total = price * quantity", "tax = total * 0.1", "final_price = total + tax"]
}

Expression nodes can fail in two cases:

  • Division by zero
  • Reference to undefined variable

When an error occurs, execution routes to the error connection if defined, otherwise the workflow fails.

Delegate execution to another workflow:

{
"id": "run-tests",
"type": "subgraph",
"graphId": "test-workflow",
"inputMapping": {
"codeDir": "projectPath"
},
"outputMapping": {
"testResults": "results"
},
"connections": {
"success": "next-step"
}
}
PropertyRequiredDescription
graphIdYesReferenced workflow ID
inputMappingYesParent context -> subgraph context
outputMappingYesSubgraph context -> parent context
connections.successYesNext node on success
connections.errorNoNext node on failure

Send automated notifications via Telegram:

{
"id": "notify-complete",
"type": "telegram-notification",
"message": "Workflow {{workflowName}} completed successfully",
"parseMode": "Markdown",
"connections": {
"default": "next-step",
"error": "notification-failed"
}
}
PropertyRequiredDescription
messageYesNotification text (supports templates)
parseModeNoMessage format: “Markdown” or “HTML”
connections.defaultYesNext node after sending
connections.errorNoNext node on API failure

Define expected response structure using JSON Schema:

{
"inputSchema": {
"type": "object",
"properties": {
"summary": {
"type": "string",
"description": "Brief summary of findings"
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"priority": { "type": "number" }
}
}
}
},
"required": ["summary"]
}
}

Automatic nodes execute without agent interaction. They run server-side and immediately continue to the next node. Used for note storage operations.

Reads notes matching filter criteria into context variable:

{
"type": "read-note",
"id": "load-notes",
"outputVariable": "projectNotes",
"filter": {
"tag": "{{projectTag}}",
"keyPattern": "project-"
},
"singleMode": false,
"connections": {
"default": "next-node",
"error": "error-handler"
}
}
PropertyRequiredDescription
outputVariableYesContext variable to store results
filter.tagNoFilter by exact tag
filter.keyPatternNoFilter by key prefix
filter.keySearchNoSearch in key (contains)
singleModeNoReturn object instead of array
connections.errorNoError handler node

Writes data from context to notes:

{
"type": "write-note",
"id": "save-results",
"key": "results-{{timestamp}}",
"source": "analysisResults",
"tags": ["analysis"],
"connections": {
"default": "next-node"
}
}
PropertyRequiredDescription
keyNo*Note key (required in single mode)
sourceYesContext variable with value
tagsNoTags to assign
batchModeNoProcess array of notes

Find-or-create operation:

{
"type": "upsert-note",
"id": "upsert-config",
"search": { "tag": "config" },
"keyTemplate": "{{projectId}}-config",
"value": "configData",
"connections": {
"default": "next-node"
}
}
PropertyRequiredDescription
search.tagNoSearch by tag
search.keyPatternNoSearch by key prefix
keyTemplateYesKey for new note if not found
valueYesContext variable with note value
  1. Start with start - Every workflow needs exactly one start node
  2. End with end - Use end nodes to mark completion points
  3. Clear Directives - Be specific about what the agent should do
  4. Verifiable Conditions - Completion conditions should be objectively measurable
  5. Schema Validation - Use inputSchema for structured responses
  6. Error Paths - Define error connections for graceful failure handling