// multi-agent-review.tsx
import { createSmithers, Task, Sequence, Parallel } from "smithers-orchestrator";
import { ToolLoopAgent as Agent } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { z } from "zod";
const { Workflow, smithers } = createSmithers({
review: z.object({
approved: z.boolean(),
feedback: z.string(),
}),
verdict: z.object({
approved: z.boolean(),
summary: z.string(),
}),
});
const securityReviewer = new Agent({
model: anthropic("claude-sonnet-4-5-20250929"),
instructions:
"You are a security-focused code reviewer. Look for vulnerabilities, injection risks, and auth issues. Return your verdict and detailed feedback.",
});
const qualityReviewer = new Agent({
model: anthropic("claude-sonnet-4-5-20250929"),
instructions:
"You are a code quality reviewer. Evaluate readability, test coverage, error handling, and adherence to best practices. Return your verdict and detailed feedback.",
});
const aggregator = new Agent({
model: anthropic("claude-sonnet-4-5-20250929"),
instructions:
"You receive two code reviews. Synthesize them into a single verdict. Approve only if both reviewers approve.",
});
export default smithers((ctx) => {
const secReview = ctx.outputMaybe("review", { nodeId: "security-review" });
const qualReview = ctx.outputMaybe("review", { nodeId: "quality-review" });
return (
<Workflow name="multi-agent-review">
<Sequence>
{/* Both reviews run concurrently */}
<Parallel maxConcurrency={2}>
<Task id="security-review" output="review" agent={securityReviewer}>
Review this PR diff for security issues:{"\n\n"}
```diff{"\n"}- const token = req.query.token;{"\n"}+ const token =
sanitize(req.headers.authorization);{"\n"}```
</Task>
<Task id="quality-review" output="review" agent={qualityReviewer}>
Review this PR diff for code quality:{"\n\n"}
```diff{"\n"}- const token = req.query.token;{"\n"}+ const token =
sanitize(req.headers.authorization);{"\n"}```
</Task>
</Parallel>
{/* Aggregate once both reviews are complete */}
<Task id="aggregate" output="verdict" agent={aggregator}>
Combine these two reviews into a final verdict:{"\n\n"}
Security review: {secReview?.approved ? "APPROVED" : "REJECTED"} -{" "}
{secReview?.feedback}
{"\n\n"}
Quality review: {qualReview?.approved ? "APPROVED" : "REJECTED"} -{" "}
{qualReview?.feedback}
</Task>
</Sequence>
</Workflow>
);
});