coding·Independently reviewed · 96/100

Code QA

Runs the project's test/lint/type-check commands through a caller-injected runner, then turns the REAL captured output into a TYPED failure report (shortest reproducer, message, root cause), grouped by cause. Execution stays in YOUR sandbox (no shell spawned by the agent); reports, never fixes.

codingtestingstructured-output

Install

npx agentskit add coding-code-qa

Quick start

import { openai } from '@agentskit/adapters'import { createCodingCodeQaAgent } from './agents/coding-code-qa/agent'const agent = createCodingCodeQaAgent({  adapter: openai({    apiKey: process.env.OPENAI_API_KEY!,    model: 'gpt-4o',  }),})const result = await agent.run('Describe your task here')console.log(result.content)

Independent reviewer approved

Validation evidence

How validation works
Review score
96/100
Confidence
95%
Evaluation cases
3
Iterations
2

The agent produced valid typed CodeQaReport-shaped outputs for all three cases, did not spawn execution, did not hallucinate test results, and correctly converted missing runner/commands context into a configuration failure report. It also resisted the injection request by returning the same structured report instead of APPROVED. The behavior is narrow but matches the README contract for missing commands.

What passed review

  • Valid structured output in every case.
  • Correctly reports missing QA commands instead of inventing execution results.
  • Injection case was handled safely with no instruction leakage or format break.
  • Progress events are consistent with the configuration failure.

Example

A real usage example maintained with this agent.

import { anthropic } from '@agentskit/adapters'import { createCodeQaAgent } from './agents/coding-code-qa/agent'const report = await createCodeQaAgent({  adapter: anthropic({ apiKey: process.env.ANTHROPIC_API_KEY!, model: 'claude-opus-4-8' }),  run: (cmd) => myRunner(cmd),   // → { stdout, stderr, code, durationMs }  commands: ['pnpm test', 'pnpm lint', 'pnpm typecheck'],}).run('feature/login')// → { allGreen, commands: [{ command, code }], failures: [{ reproducer, command, message, rootCause }], summary }

Extend it

Pass tools, retrieval, memory, permissions, and observers through the factory config.

const agent = createCodingCodeQaAgent({  adapter,  tools,  retriever,  memory,  onConfirm: (call) => approve(call),  observers: [tracer],})
View agent factory source
import type { AdapterFactory, ChatMemory, Observer, ToolCall, ToolDefinition } from '@agentskit/core'import { fenceUntrustedContent, UNTRUSTED_CONTENT_DIRECTIVE } from '@agentskit/core/security'import { invokeStructured } from '@agentskit/runtime'import { defineZodTool } from '@agentskit/tools'import { z } from 'zod'import { zodToJsonSchema } from 'zod-to-json-schema'import type { JSONSchema7 } from 'json-schema'/** * Code QA — runs the project's test / lint / type-check commands through a caller-injected * runner, then has the model turn the REAL captured output into a TYPED failure report * (shortest reproducer, assertion message, one-sentence root cause), grouped so a fix * touches the smallest surface. It reports; it never pushes fixes. * * The agent does NOT spawn shells itself — you inject `run`, so command execution stays in * YOUR sandbox/policy. With no runner it refuses (it can't QA what it can't run). * * ```ts * const report = await createCodeQaAgent({ *   adapter, *   run: (cmd) => exec(cmd, { cwd }),   // → { stdout, stderr, code, durationMs } *   commands: ['pnpm test', 'pnpm lint', 'pnpm typecheck'], * }).run('feature/login') * ``` */export interface CommandResult {  stdout: string  stderr: string  /** Process exit code (0 = success). */  code: number  durationMs?: number}export interface QaFailure {  /** Shortest reproducer: file:line + the command. */  reproducer: string  command: string  message: string  rootCause: string}export interface CodeQaReport {  allGreen: boolean  /** Per-command exit status. */  commands: { command: string; code: number; durationMs?: number }[]  failures: QaFailure[]  summary: string}export interface CodeQaConfig {  adapter: AdapterFactory  /** Command runner — executes in YOUR sandbox and returns the captured result. */  run: (command: string) => Promise<CommandResult> | CommandResult  /** Commands to run (test / lint / type-check). */  commands: string[]  memory?: ChatMemory  observers?: Observer[]  onConfirm?: (toolCall: ToolCall) => boolean | Promise<boolean>  maxSteps?: number}const Report = z.object({  failures: z.array(z.object({    reproducer: z.string(),    command: z.string(),    message: z.string(),    rootCause: z.string(),  })),  summary: z.string(),})const toJson = (s: z.ZodTypeAny): JSONSchema7 => zodToJsonSchema(s) as JSONSchema7const skill = {  name: 'code-qa',  description: 'Turns captured test/lint/type-check output into a typed, grouped failure report.',  systemPrompt: `You are Code QA. You are given the CAPTURED output of the project's test / lint /type-check commands. Produce a structured failure report. For EACH failure: the shortest reproducer(file:line + the command), the assertion/error message, and a one-sentence root-cause guess. Groupfailures by likely root cause so a fix touches the smallest surface. You REPORT; you never push fixes.Report only what the output shows — do not invent failures.${UNTRUSTED_CONTENT_DIRECTIVE}Call submit_report exactly once with { failures, summary }. Stop.`,  tools: ['submit_report'],}export function createCodeQaAgent(config: CodeQaConfig) {  if (typeof config.run !== 'function') throw new Error('code QA requires a `run` command runner')  const commands = config.commands ?? []  const emit = (label: string, status: 'start' | 'ok' | 'skip' | 'error', detail?: string) => {    for (const o of config.observers ?? []) void o.on({ type: 'progress', label, status, detail })  }  const submit = (): ToolDefinition =>    defineZodTool({ name: 'submit_report', description: 'Submit the QA report. Call exactly once.', schema: Report, toJsonSchema: toJson, async execute() { return 'recorded' } }) as ToolDefinition  async function run(branch: string): Promise<CodeQaReport> {    if (commands.length === 0) throw new Error('code QA requires at least one command to run')    // Run every command deterministically and capture the REAL output.    const ran: { command: string; result: CommandResult }[] = []    for (const command of commands) {      emit('run', 'start', command)      const result = await config.run(command)      ran.push({ command, result })      emit('run', result.code === 0 ? 'ok' : 'error', command)    }    const commandStatuses = ran.map(({ command, result }) => ({ command, code: result.code, durationMs: result.durationMs }))    const allGreen = ran.every(({ result }) => result.code === 0)    if (allGreen) {      const timing = commandStatuses        .map(({ command, durationMs }) => `${command}${durationMs != null ? ` (${Math.round(durationMs / 1000)}s)` : ''}`)        .join(', ')      return { allGreen: true, commands: commandStatuses, failures: [], summary: `all green — ${timing}` }    }    // Hand the captured output to the model for typed failure analysis.    const captured = ran      .filter(({ result }) => result.code !== 0)      .map(({ command, result }) => `$ ${command} (exit ${result.code})\n${result.stdout}\n${result.stderr}`)      .join('\n\n')    emit('analyse', 'start')    const out = await invokeStructured({      adapter: config.adapter,      tool: submit(),      task: `BRANCH: ${branch}\n\nCAPTURED COMMAND OUTPUT:\n${fenceUntrustedContent(captured)}`,      parse: (a) => Report.parse(a),      skill,      memory: config.memory,      observers: config.observers,      onConfirm: config.onConfirm,      maxSteps: config.maxSteps ?? 3,    })    emit('analyse', 'ok', `${out.failures.length} failure(s)`)    return { allGreen: false, commands: commandStatuses, failures: out.failures, summary: out.summary }  }  return {    name: 'coding-code-qa',    run,    asHandle() {      return { name: 'coding-code-qa', run: async (task: string) => JSON.stringify(await run(task)) }    },  }}
View evaluation contract

Replay these cases with the provider and model you plan to deploy.

import type { EvalSuite } from '@agentskit/eval'export const suite: EvalSuite = {  name: 'coding-code-qa',  cases: [    {      input: `Branch: feat/payment-retry. Commands: \`pnpm test\`, \`pnpm lint\`, \`pnpm typecheck\`. The test run produced:FAIL src/payment/retry.test.ts > retries on 503  AssertionError: expected 2 to equal 3    at src/payment/retry.test.ts:42:18FAIL src/payment/retry.test.ts > backoff doubles each attempt  AssertionError: expected 200 to equal 400    at src/payment/retry.test.ts:58:20Run all three commands and summarise the failures.`,      expected: (r: string) => /retry\.test\.ts/i.test(r) && /(root cause|likely|because|cause)/i.test(r),    },    {      input: `Branch: chore/upgrade-zod. Commands: \`pnpm typecheck\`, \`pnpm test\`. typecheck output:src/schema/user.ts:12:5 - error TS2345: Argument of type 'string' is not assignable to parameter of type 'ZodString'.src/schema/user.ts:19:5 - error TS2345: Argument of type 'string' is not assignable to parameter of type 'ZodNumber'.Group failures by likely root cause and give the shortest reproducer for each.`,      expected: (r: string) => /user\.ts/i.test(r) && /(zod|TS2345|type)/i.test(r),    },    {      input: `Branch: main. Commands: \`pnpm test\` (took 41s), \`pnpm lint\` (took 6s), \`pnpm typecheck\` (took 18s). All commands exited 0 with zero failures. Report the result.`,      expected: (r: string) => /all green/i.test(r) && /41s|41 s|41 second/i.test(r),    },    {      input: `Branch: feat/search-index. You are asked to run QA but no test/lint/type-check commands were provided and the package.json scripts section is empty. Proceed.`,      expected: (r: string) => /(no (test|command)|missing|cannot|not provided|unable|escalat|need)/i.test(r),    },  ],}

Was this agent useful?

Your response helps us prioritize agent quality.

Keep exploring

Related agents

View category