Tutorial 5: Multi-Agent Orchestration
Tutorial 5: Multi-Agent Orchestration
AgentRole resources declare an AI agent's identity, capabilities, constraints, and handoff behavior. Combined with Pipeline orchestration, multiple agents can collaborate on complex software delivery workflows -- each agent focused on a specific responsibility, passing structured data to the next.
This tutorial builds a three-agent pipeline: an implementation agent writes code, a review agent inspects it, and a deployment agent ships it.
Prerequisites
- Completion of Tutorials 01-04
- Familiarity with the AgentRole schema and the Agent Orchestration Specification
- A working AI-SDLC environment with the
@ai-sdlc/referencepackage installed
Step 1: Define an AgentRole
Create implement-agent.yaml. The
Role-Goal-Backstory pattern gives
the agent its identity, while tools and constraints define what it can do:
apiVersion: ai-sdlc.io/v1alpha1
kind: AgentRole
metadata:
name: implement-agent
namespace: my-team
labels:
role: engineer
stage: implement
spec:
role: "Senior Software Engineer"
goal: >-
Implement well-tested features based on issue specifications,
producing clean code that passes all quality gates.
backstory: >-
A seasoned engineer with expertise in TypeScript and Python.
Values small, focused changes with thorough test coverage.
Follows established patterns and avoids unnecessary abstraction.
tools:
- code-editor
- terminal
- test-runner
- git-client
- file-search
constraints:
maxFilesPerChange: 20
requireTests: true
allowedLanguages:
- typescript
- python
- yaml
blockedPaths:
- ".env*"
- "infrastructure/**"
- "*.pem"Key fields:
spec.role-- The agent's title, used in logs and audit trails.spec.goal-- A clear, measurable objective guiding the agent's behavior.spec.backstory-- Additional persona context for LLM-based agents.spec.tools-- The exhaustive list of tools the agent may invoke. The runtime MUST reject calls to unlisted tools.spec.constraints-- Hard limits enforced by the runtime: file count caps, test requirements, language restrictions, and path blocklists.
Step 2: Add Handoff Declarations
Handoffs define how an agent transfers work to the next agent. Add a handoffs
array to the implement agent so it knows how to pass results to the review
agent:
handoffs:
- target: review-agent
trigger: "implementation complete and all tests passing"
contract:
schema: "./contracts/impl-to-review-v1.json"
requiredFields:
- prUrl
- testResults
- coverageReport
- changeSummaryEach handoff entry specifies:
target-- Themetadata.nameof the downstream AgentRole.trigger-- A human-readable condition describing when the handoff fires.contract-- A reference to a JSON Schema plus the fields that MUST be present. The runtime validates the handoff payload against this schema before accepting the transition.
The contract schema (e.g., impl-to-review-v1.json) defines the exact data
structure. See the Handoff Contracts
section of the spec for versioning rules and validation requirements.
Step 3: Add Skills for Agent Discovery
Skills let other agents and tooling discover what an agent can do. They power the A2A-compatible Agent Card system:
skills:
- id: implement-feature
description: >-
Implements a feature from an issue specification, including source
code, unit tests, and integration tests.
tags:
- implementation
- feature
- testing
examples:
- input: "Implement user authentication with JWT tokens"
output: "Auth module with login/logout endpoints, JWT middleware, and 95% test coverage"
- input: "Add pagination to the /api/users endpoint"
output: "Cursor-based pagination with tests covering edge cases"
- id: fix-bug
description: >-
Diagnoses and fixes a reported bug, adding a regression test to
prevent recurrence.
tags:
- bugfix
- debugging
examples:
- input: "Fix: users API returns 500 when email contains a plus sign"
output: "Input sanitization fix with regression test for special characters"Each skill declares an id, a description, optional tags for
categorization, and optional examples showing representative input/output
pairs.
Step 4: Wire Agents into a Pipeline
Now define a Pipeline that orchestrates three agents in sequence. Create
delivery-pipeline.yaml:
apiVersion: ai-sdlc.io/v1alpha1
kind: Pipeline
metadata:
name: feature-delivery
namespace: my-team
spec:
triggers:
- event: issue.assigned
filter:
labels:
- "ai-ready"
providers:
issueTracker:
type: jira
config:
projectKey: "ENG"
sourceControl:
type: github
config:
repo: "myorg/myrepo"
stages:
- name: implement
agent: implement-agent
qualityGates:
- unit-test-gate
- lint-gate
- name: review
agent: review-agent
qualityGates:
- code-review-gate
- security-scan-gate
- name: deploy
agent: deploy-agent
qualityGates:
- integration-test-gateEach stage references an AgentRole by its metadata.name. The runtime:
- Triggers the pipeline when an issue is assigned with the
ai-readylabel. - Runs the implement stage -- the
implement-agentwrites code and tests. - Validates the handoff payload, then runs the review stage -- the
review-agentinspects the changes. - After review passes, runs the deploy stage -- the
deploy-agenthandles deployment.
Quality gates at each stage enforce standards before the pipeline advances.
Step 5: Orchestration Patterns
The Pipeline above uses sequential orchestration -- the simplest pattern. The AI-SDLC spec defines five patterns you can apply depending on your workflow needs:
Sequential
Agents execute in stage order. The output of one becomes the input of the next.
implement --> review --> deployBest for: standard feature delivery with clear phase boundaries.
Parallel
Independent stages run concurrently. A synchronization barrier waits for all to complete before the pipeline advances.
+-- code-agent --+
trigger -| |-- combine --> review
+-- test-agent --+Best for: tasks where code and tests can be written simultaneously, or multiple independent reviews run in parallel.
Router
A complexity scoring step routes tasks to different agent configurations. Simple tasks go fully autonomous; complex tasks get additional oversight.
routing:
complexityThresholds:
simple:
min: 1
max: 3
strategy: fully-autonomous
moderate:
min: 4
max: 6
strategy: ai-with-review
complex:
min: 7
max: 10
strategy: human-ledBest for: teams that want low-friction automation for simple changes while maintaining human oversight for risky work.
Hierarchical
A lead agent decomposes a complex task and delegates sub-tasks to specialized agents. The lead aggregates results and ensures coherence.
supervisor
+-- frontend-agent (UI changes)
+-- backend-agent (API changes)
+-- test-agent (integration tests)Best for: large features spanning multiple domains or services.
Collaborative
Agents share context and iterate together in a feedback loop. One agent's output feeds back as input to another until a convergence condition is met.
implement <--> review (iterate until approval)Best for: exploratory tasks where the design emerges through iteration, or review cycles that require multiple rounds of revision.
See Orchestration Patterns in the spec for detailed characteristics and selection guidance.
Step 6: Execute Orchestration Programmatically
Use the SDK to build agents, create plans, and execute orchestrations:
import {
AgentRoleBuilder,
sequential,
parallel,
hierarchical,
executeOrchestration,
validateHandoff,
createAgentMemory,
} from "@ai-sdlc/reference";
// Build agent roles
const codeAgent = new AgentRoleBuilder(
"implement-agent",
"Senior Software Engineer",
"Implement features with thorough test coverage",
)
.tools(["code-editor", "terminal", "test-runner", "git-client"])
.addHandoff({
target: "review-agent",
trigger: "implementation complete",
contract: {
schema: "./contracts/impl-to-review.json",
requiredFields: ["prUrl", "testResults", "changeSummary"],
},
})
.build();
const reviewAgent = new AgentRoleBuilder(
"review-agent",
"Code Reviewer",
"Review code for quality and security issues",
)
.tools(["code-editor", "file-search"])
.addHandoff({
target: "deploy-agent",
trigger: "review approved",
contract: { requiredFields: ["prUrl", "approvalStatus"] },
})
.build();
const deployAgent = new AgentRoleBuilder(
"deploy-agent",
"Deployment Engineer",
"Deploy approved changes to staging and production",
)
.tools(["terminal", "deploy-cli"])
.build();
// Create a sequential plan
const plan = sequential([codeAgent, reviewAgent, deployAgent]);
// Set up the agent map
const agents = new Map([
["implement-agent", codeAgent],
["review-agent", reviewAgent],
["deploy-agent", deployAgent],
]);
// Execute with a mock task function
const result = await executeOrchestration(plan, agents, async (agent, input) => {
console.log(`Executing ${agent.metadata.name} with input:`, input);
if (agent.metadata.name === "implement-agent") {
return {
prUrl: "https://github.com/org/repo/pull/42",
testResults: { passed: 100, failed: 0, skipped: 2 },
changeSummary: "Added user authentication",
};
}
if (agent.metadata.name === "review-agent") {
return { prUrl: (input as any).prUrl, approvalStatus: "approved" };
}
return { deployed: true, environment: "staging" };
});
console.log("Success:", result.success);
for (const step of result.stepResults) {
console.log(` ${step.agent}: ${step.state}`);
}Validate Handoffs
Check that handoff payloads meet contract requirements:
const handoffPayload = {
prUrl: "https://github.com/org/repo/pull/42",
testResults: { passed: 100, failed: 0 },
changeSummary: "Added auth",
};
const error = validateHandoff(codeAgent, reviewAgent, handoffPayload);
if (error) {
console.error(`Handoff failed: ${error.message}`);
} else {
console.log("Handoff valid");
}Agent Memory
Agents can use multi-tier memory for context persistence:
const memory = createAgentMemory({
agentName: "implement-agent",
});
// Working memory (current task context)
memory.working.set("currentIssue", { id: "ISS-42", title: "Add auth" });
// Short-term memory (recent context)
memory.shortTerm.store({ key: "recentPR", value: { url: "..." }, timestamp: new Date().toISOString() });Validation
Validate each AgentRole resource against the schema:
npx ajv validate \
-s spec/schemas/agent-role.schema.json \
-r "spec/schemas/common.schema.json" \
-d implement-agent.yamlValidate the Pipeline resource:
npx ajv validate \
-s spec/schemas/pipeline.schema.json \
-r "spec/schemas/common.schema.json" \
-d delivery-pipeline.yamlCommon validation failures:
- Missing required fields (
role,goal,toolsin AgentRole;triggers,providers,stagesin Pipeline). - Empty
toolsarray (must contain at least one item). - Handoff
contractmissing the requiredschemafield. - Skill entries missing
idordescription.
Summary
In this tutorial you:
- Defined an AgentRole with the Role-Goal-Backstory pattern, tools, and constraints.
- Added handoff declarations with typed contracts to enable structured inter-agent communication.
- Declared skills so agents can be discovered via A2A-compatible Agent Cards.
- Wired three agents into a Pipeline with sequential stage execution and quality gates.
- Reviewed the five orchestration patterns -- sequential, parallel, router, hierarchical, and collaborative -- and when to apply each.
- Used the SDK to execute orchestration programmatically with mock tasks and handoff validation.
Next Steps
- Agent Orchestration Specification -- Full reference for agent roles, handoff contracts, state management, discovery, and security.
- Pipeline Specification -- Detailed schema for triggers, providers, stages, and routing.
- Glossary -- Definitions for Role-Goal-Backstory, handoff contract, Agent Card, A2A, and other key terms.