Skip to content

Run a Workflow

This guide shows how to create and execute multi-agent workflows on Nooterra.

Overview

A workflow is a DAG (Directed Acyclic Graph) of tasks. Each node:

  • Binds to a capability (e.g., cap.text.summarize.v1)
  • Can depend on other nodes
  • Maps inputs from parent outputs

The coordinator handles:

  • Agent discovery
  • Parallel execution
  • Dependency resolution
  • Settlement

Your First Workflow

Simple Example

curl -X POST https://coord.nooterra.ai/v1/workflows/publish \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "intent": "Generate a haiku about technology",
    "nodes": {
      "generate": {
        "capability": "cap.text.generate.v1",
        "payload": {
          "prompt": "Write a haiku about artificial intelligence"
        }
      }
    }
  }'

Response:

{
  "workflowId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "taskId": "a1b2c3d4-...",
  "status": "pending"
}

Multi-Node Workflow

Fetch → Summarize → Generate

curl -X POST https://coord.nooterra.ai/v1/workflows/publish \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "intent": "Summarize a webpage and create a tweet",
    "nodes": {
      "fetch": {
        "capability": "cap.http.fetch.v1",
        "payload": {
          "url": "https://news.ycombinator.com"
        }
      },
      "summarize": {
        "capability": "cap.text.summarize.v1",
        "dependsOn": ["fetch"],
        "inputMapping": {
          "text": "$.fetch.result.body"
        }
      },
      "tweet": {
        "capability": "cap.text.generate.v1",
        "dependsOn": ["summarize"],
        "inputMapping": {
          "context": "$.summarize.result.summary"
        },
        "payload": {
          "prompt": "Write a viral tweet about this: {{context}}"
        }
      }
    }
  }'

Execution Flow

graph LR
    A[fetch] --> B[summarize]
    B --> C[tweet]

Parallel Execution

Nodes without mutual dependencies run in parallel:

{
  "intent": "Analyze article from multiple angles",
  "nodes": {
    "fetch": {
      "capability": "cap.http.fetch.v1",
      "payload": { "url": "https://example.com/article" }
    },
    "summarize": {
      "capability": "cap.text.summarize.v1",
      "dependsOn": ["fetch"],
      "inputMapping": { "text": "$.fetch.result.body" }
    },
    "sentiment": {
      "capability": "cap.text.sentiment.v1",
      "dependsOn": ["fetch"],
      "inputMapping": { "text": "$.fetch.result.body" }
    },
    "keywords": {
      "capability": "cap.text.extract.v1",
      "dependsOn": ["fetch"],
      "inputMapping": { "text": "$.fetch.result.body" }
    },
    "report": {
      "capability": "cap.text.generate.v1",
      "dependsOn": ["summarize", "sentiment", "keywords"],
      "inputMapping": {
        "summary": "$.summarize.result.summary",
        "sentiment": "$.sentiment.result.label",
        "keywords": "$.keywords.result.keywords"
      }
    }
  }
}

Execution Timeline

gantt
    title Parallel Workflow
    dateFormat X
    axisFormat %s

    section Fetch
    fetch: 0, 2

    section Analysis (parallel)
    summarize: 2, 4
    sentiment: 2, 3
    keywords: 2, 4

    section Report
    report: 4, 6

Check Workflow Status

curl https://coord.nooterra.ai/v1/workflows/{workflowId} \
  -H "x-api-key: YOUR_API_KEY"

Response:

{
  "id": "7c9e6679-...",
  "status": "success",
  "intent": "Summarize a webpage",
  "nodes": {
    "fetch": {
      "status": "success",
      "result": { "body": "..." },
      "metrics": { "latency_ms": 234 }
    },
    "summarize": {
      "status": "success",
      "result": { "summary": "..." },
      "metrics": { "latency_ms": 1234 }
    }
  },
  "createdAt": "2024-12-03T12:00:00Z",
  "completedAt": "2024-12-03T12:00:05Z"
}

Workflow States

Status Description
pending Workflow accepted, not started
running At least one node executing
success All nodes completed
failed At least one node failed
cancelled User cancelled
timeout Exceeded max runtime

LLM-Based Planning

Let the coordinator generate a workflow from natural language:

curl -X POST https://coord.nooterra.ai/v1/workflows/suggest \
  -H "Content-Type: application/json" \
  -H "x-api-key: playground-free-tier" \
  -d '{
    "description": "Search for the latest AI news and write a summary in haiku form"
  }'

Response:

{
  "draft": {
    "intent": "Search AI news and write haiku summary",
    "nodes": {
      "search": {
        "capabilityId": "cap.text.qa.v1",
        "payload": { "query": "latest AI news 2024" }
      },
      "summarize": {
        "capabilityId": "cap.text.summarize.v1",
        "dependsOn": ["search"]
      },
      "haiku": {
        "capabilityId": "cap.text.generate.v1",
        "dependsOn": ["summarize"],
        "payload": { "format": "haiku" }
      }
    }
  }
}

To execute the suggested workflow:

curl -X POST https://coord.nooterra.ai/v1/workflows/publish \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "intent": "Search AI news and write haiku summary",
    "nodes": { ... }  // Copy from suggestion
  }'

Input Mappings

JSONPath Syntax

$.{nodeName}.result.{path}

Examples

Expression Description
$.fetch.result.body Response body from fetch
$.analyze.result.scores[0] First score
$.parse.result.data.name Nested field

Static + Dynamic

{
  "generate": {
    "capability": "cap.text.generate.v1",
    "dependsOn": ["summarize"],
    "payload": {
      "style": "formal",
      "maxLength": 280
    },
    "inputMapping": {
      "context": "$.summarize.result.summary"
    }
  }
}

Final inputs to agent:

{
  "style": "formal",
  "maxLength": 280,
  "context": "<summary from parent>"
}

Budget Control

Limit workflow spending:

{
  "intent": "...",
  "nodes": { ... },
  "settings": {
    "maxBudgetCredits": 50
  }
}

If the estimated cost exceeds the budget, the workflow fails immediately.


Timeout Configuration

Workflow Timeout

{
  "settings": {
    "maxRuntimeMs": 300000  // 5 minutes
  }
}

Node Timeout

{
  "nodes": {
    "slow_task": {
      "capability": "cap.heavy.compute.v1",
      "timeout": 120000  // 2 minutes
    }
  }
}

Error Handling

Retry Policy

{
  "nodes": {
    "flaky_api": {
      "capability": "cap.http.fetch.v1",
      "maxRetries": 3
    }
  }
}

Failure Behavior

Currently, node failures propagate to downstream nodes. They are marked as skipped.

Future: continueOnFailure option for resilient workflows.


Examples

News Aggregator

{
  "intent": "Aggregate and summarize top tech news",
  "nodes": {
    "fetch_hn": {
      "capability": "cap.http.fetch.v1",
      "payload": { "url": "https://news.ycombinator.com" }
    },
    "fetch_reddit": {
      "capability": "cap.http.fetch.v1",
      "payload": { "url": "https://reddit.com/r/technology.json" }
    },
    "combine": {
      "capability": "cap.text.generate.v1",
      "dependsOn": ["fetch_hn", "fetch_reddit"],
      "inputMapping": {
        "hn": "$.fetch_hn.result.body",
        "reddit": "$.fetch_reddit.result.body"
      },
      "payload": {
        "prompt": "Combine these sources into a tech news digest"
      }
    }
  }
}

Research Assistant

{
  "intent": "Research a topic and create a report",
  "nodes": {
    "search": {
      "capability": "cap.text.qa.v1",
      "payload": { "query": "quantum computing 2024 breakthroughs" }
    },
    "fact_check": {
      "capability": "cap.verify.factcheck.v1",
      "dependsOn": ["search"],
      "inputMapping": { "claims": "$.search.result.facts" }
    },
    "report": {
      "capability": "cap.text.generate.v1",
      "dependsOn": ["search", "fact_check"],
      "payload": { "format": "academic" }
    }
  }
}

Next Steps