TurfAITurfAI User Guide
Modules

Squads

Teams of agents collaborating over a shared blackboard.

What it is

A Squad is a named team of agents with an ordered pipeline of tasks and an execution strategy. Agents collaborate through a shared blackboard — each task writes its result to an output_key that downstream tasks read — with every write recorded in an audit trail. Think of it as a project team where each member has a role and everyone shares a whiteboard.

For when to reach for a squad versus a single agent or a workflow, see the decision guide.

When to use it

Use a squad when no single agent can hold the whole job — when you'd otherwise overload one agent with several unrelated responsibilities. Split them into specialists: research → write → review, or evidence → coverage → valuation → offer → compliance.

How it works

Process flow — sequential vs hierarchical:

Call flow — kickoff to result:

Under the hood the sequential processor topologically sorts the tasks (Kahn's algorithm), then runs each in order. A task only sees blackboard entries written by its depends_on tasks (plus the initial kickoff inputs) — unrelated branches are filtered out. Root tasks (no depends_on) receive the raw kickoff context. Hierarchical squads instead run a single manager agent that is given the agent roster and task list and delegates via a delegate tool.

Sub-features

  • Process typesSequential (dependency order) and Hierarchical (manager delegates).
  • Task pipeline builder — per-task id, description, assigned agent, depends-on, output_key, expected output.
  • Real-time validation — circular-dependency, duplicate-id, and invalid-agent detection.
  • Run tab — JSON kickoff inputs; results show per-task status, answer, tools used, iterations, final output, audit trail, and the full blackboard.

Configuration parameters

These map directly to the squad content type. agents and tasks are JSON arrays of objects (shapes below).

ParameterTypeNotes
namestring (required)Squad identity.
slugstring (unique, read-only)Auto-generated URL-safe id.
descriptiontextHuman-readable purpose.
processenum: sequential | hierarchicalDefaults to sequential.
manager_agentrelation → agentRequired for hierarchical squads; ignored for sequential.
agentsJSON arraySquad members. Defaults to [].
tasksJSON arrayThe task pipeline. Defaults to [].
max_total_iterationsintegerSquad-wide budget, default 30 — not per-task (see below).
activebooleanDefaults to true; inactive squads cannot be kicked off.

Agent object (each entry in agents[]):

{ "agent_slug": "researcher", "role": "Research topics thoroughly using available tools" }

Task object (each entry in tasks[]):

{
  "id": "write",
  "description": "Write a detailed report from the research findings",
  "agent_slug": "writer",
  "depends_on": ["research"],
  "output_key": "draft",
  "expected_output": "A 600-word article with headings"
}

output_key defaults to the task id when omitted, and expected_output is optional guidance appended to the agent's goal.

max_total_iterations is squad-wide, not per-task. It is a single budget shared across the whole pipeline. Each task consumes the agent's iteration count from this pool, and each agent's own max_iterations is additionally capped to whatever budget remains. If the budget runs out, the remaining tasks are written to the blackboard as (skipped — iteration limit reached) with status skipped.

Dependencies

  • Agents — squad members are existing agents referenced by agent_slug (and a manager_agent for hierarchical). An agent referenced by a task must exist and be active.
  • DMS Squad controller/service — CRUD, validation, slug generation, kickoff→poll.
  • Squad processor — sequential/hierarchical execution, blackboard, audit trail, agent orchestration.

Tips & best practices

  • Sequential vs hierarchical. Choose sequential when the order is known up front (research → write → edit) — it is more predictable and every dependency is explicit. Choose hierarchical only when the right order genuinely depends on intermediate results and you want a manager to decide at runtime; you trade determinism for flexibility.
  • Name output_keys for what they hold, not the step. findings, draft, final_copy read better downstream than task1/task2. A clear key is what the next agent actually sees on the blackboard.
  • Wire depends_on deliberately. A task only receives blackboard entries from its declared dependencies (plus the kickoff inputs). Forget to list a dependency and the agent won't see that upstream output — even if the task ran earlier.
  • Keep the pipeline small. Three to five focused tasks beats a sprawling graph. More tasks means more iterations against the shared max_total_iterations budget and more places to fail.
  • Set roles tightly. Each role should be a one-line job description ("Edit for clarity and accuracy"), not a second prompt. Overlapping roles make agents redo each other's work.
  • Manager-agent design (hierarchical). Pick a strong-reasoning agent as the manager and keep its worker roster short with crisp roles — the manager only knows agents by their slug and role text. Give workers the tools they need; the manager itself only gets delegate and generate_text.

Anti-patterns

  • One mega-task that asks a single agent to "research, write, and edit" — that's just an agent, not a squad. Split it or use Agents directly.
  • Deep dependency chains where every task depends on every prior task — collapse them or you'll burn the iteration budget.
  • Reusing the same output_key across tasks — the later write silently overwrites the earlier one on the blackboard.

Concrete examples

A sequential research → write → edit squad. Members:

{
  "process": "sequential",
  "max_total_iterations": 30,
  "agents": [
    { "agent_slug": "researcher", "role": "Research topics thoroughly using available tools" },
    { "agent_slug": "writer", "role": "Write clear, well-structured content from research" },
    { "agent_slug": "editor", "role": "Review and improve content for clarity and accuracy" }
  ],
  "tasks": [
    {
      "id": "research",
      "description": "Research {{context}} comprehensively",
      "agent_slug": "researcher",
      "depends_on": [],
      "output_key": "findings"
    },
    {
      "id": "write",
      "description": "Write a detailed report from the research findings",
      "agent_slug": "writer",
      "depends_on": ["research"],
      "output_key": "draft",
      "expected_output": "A 600-word article with headings"
    },
    {
      "id": "edit",
      "description": "Polish the draft for clarity and accuracy",
      "agent_slug": "editor",
      "depends_on": ["write"],
      "output_key": "final_copy"
    }
  ]
}

Kick it off with {"topic": "Benefits of AI in healthcare"}. An abridged kickoff response:

{
  "data": {
    "job_id": "squad_1710859200_a1b2c3",
    "squad": "research-team",
    "result": {
      "squad": "Research & Writing Team",
      "process": "sequential",
      "final_output": "## research (by researcher)\n...\n\n## write (by writer)\n...\n\n## edit (by editor)\n...",
      "task_results": {
        "research": {
          "status": "completed",
          "agent": "researcher",
          "answer": "Key findings on AI in healthcare...",
          "tools_used": ["search_documents", "fetch_url"],
          "iterations": 3
        },
        "write": {
          "status": "completed",
          "agent": "writer",
          "answer": "Draft article...",
          "tools_used": ["generate_text"],
          "iterations": 2
        },
        "edit": {
          "status": "completed",
          "agent": "editor",
          "answer": "Polished article...",
          "tools_used": [],
          "iterations": 1
        }
      },
      "blackboard": {
        "topic": "Benefits of AI in healthcare",
        "findings": "Key findings on AI in healthcare...",
        "draft": "Draft article...",
        "final_copy": "Polished article..."
      },
      "audit_trail": [
        { "task_id": "_input", "agent_slug": "_system", "key": "topic", "timestamp": 1710859200.1 },
        { "task_id": "research", "agent_slug": "researcher", "key": "findings", "timestamp": 1710859210.4 },
        { "task_id": "write", "agent_slug": "writer", "key": "draft", "timestamp": 1710859230.8 },
        { "task_id": "edit", "agent_slug": "editor", "key": "final_copy", "timestamp": 1710859245.3 }
      ],
      "processing_time": 45.2
    }
  }
}

Note the final_output is the per-task answers stitched together under ## <task> (by <agent>) headings, the blackboard holds the last value written under each output_key (initial inputs included), and the audit_trail records every write as {task_id, agent_slug, key, timestamp}.

Limitations

  • More moving parts than a single agent — less deterministic; bound execution with max_total_iterations.
  • Save is blocked while validation errors (circular/duplicate/invalid-agent) exist.
  • Live per-task progress monitoring during a run is coming soon — today you kick off, poll, and inspect the final task_results/audit_trail.

Troubleshooting

SymptomCauseFix
Save is disabled, red "Circular" badgeTasks form a dependency cycle (A → B → A). The processor's topological sort would reject it (Circular dependency detected).Break the cycle — dependencies must flow one direction.
Red "Duplicate ID" badgeTwo tasks share the same id.Rename one; id must be unique within the squad.
Red "Invalid agent" badgeA task's agent_slug is not a squad member.Add that agent to the squad, or reassign the task to a listed member.
Task status error, "Agent '…' not found or inactive"The assigned agent was deleted or deactivated after the squad was built.Re-activate the agent or reassign the task; the pipeline continues with that task marked error.
A downstream agent ignores upstream work / "blackboard variable not found"The task's depends_on doesn't list the upstream task, so its output_key is filtered out of context.Add the upstream task id to depends_on so its output_key reaches this task.
Remaining tasks show skipped, reason iteration_limitThe squad-wide max_total_iterations budget was exhausted earlier in the pipeline.Raise max_total_iterations, shorten the pipeline, or lower per-agent max_iterations.

When a member agent fails mid-pipeline, the squad does not abort: the processor records that task's status as error, writes an (error: …) marker to its output_key, and continues to the next task. Check task_results for the failing task and the audit_trail to see what was written.

How to test

Happy path (sequential):

  1. Create two agentsresearcher and writer — and activate them.
  2. Create a Sequential squad, add both as members with roles, and define two tasks: research (agent = researcher, no deps, output_key: findings) and write (agent = writer, depends_on: [research], output_key: draft).
  3. On the Run tab, kick off with {"topic": "Benefits of AI in healthcare"}; poll until complete.
  4. Inspect the result: task_results.write.answer should build on findings; the blackboard should contain topic, findings, and draft; the audit_trail should list a _input write plus one write per task in dependency order.

Negative path (circular dependency):

  1. In the Tasks tab, set research.depends_on = [write] while write.depends_on = [research].
  2. Confirm the red "Circular" warning appears and Save is blocked — the squad cannot be persisted (and the processor would reject the graph with Circular dependency detected).
  • Agents — squad members are individual agents.
  • Workflows, agents & squads — when to choose each.
  • Roadmap: live squad-progress monitoring (per-task status streamed during a run) is coming soon.

APIs used

MethodPathPurpose
GET / POST/api/squadsList / create squads
GET / PUT / DELETE/api/squads/:idRead / update / delete
POST/api/squads/:id/kickoffExecute the squad

On this page