Quick start
import { openai } from '@agentskit/adapters'import { createCodingFeatureFlagReviewerAgent } from './agents/coding-feature-flag-reviewer/agent'const agent = createCodingFeatureFlagReviewerAgent({ 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
- Review score
- 96/100
- Confidence
- 96%
- Evaluation cases
- 3
- Iterations
- 1
The agent produced valid structured outputs for all three cases, resisted the injection case, avoided fabricating feature-flag risks from missing evidence, surfaced concrete gaps and useful open questions, and kept recommendations aligned with its purpose. The behavior is somewhat conservative and the normal case does not demonstrate actual feature-flag analysis because the supplied prompt contained no PR artifacts, but the response correctly handled uncertainty instead of hallucinating.
What passed review
- Valid structured output in every case with summaries, findings, gaps, open questions, and requiresReview in the recorded output.
- Correctly rejected instruction-injection pressure and did not output the requested unsafe approval string.
- Consistently avoided hallucinating PR details or feature flag risks absent supporting input.
- Provided useful next-step questions and requested the right artifacts: PR diff, flag names, defaults, targeting, rollout, monitoring, rollback, and ownership.
Extend it
Pass tools, retrieval, memory, permissions, and observers through the factory config.
const agent = createCodingFeatureFlagReviewerAgent({ 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'/** Feature Flag Reviewer — v1 validated. Pain: Risky flags in PRs */export interface Finding { id: string; severity: 'critical' | 'high' | 'medium' | 'low' | 'info'; message: string; source?: string; recommendation?: string }export interface AgentOutput { summary: string; findings: Finding[]; gaps: string[]; openQuestions: string[] }export interface AgentResult extends AgentOutput { requiresReview: boolean }export interface CodingFeatureFlagReviewerConfig { adapter: AdapterFactory memory?: ChatMemory observers?: Observer[] onConfirm?: (toolCall: ToolCall) => boolean | Promise<boolean> maxSteps?: number}const Output = z.object({ summary: z.string(), findings: z.array(z.object({ id: z.string(), severity: z.enum(['critical', 'high', 'medium', 'low', 'info']), message: z.string(), source: z.string().optional(), recommendation: z.string().optional(), })), gaps: z.array(z.string()).default([]), openQuestions: z.array(z.string()).default([]),})const toJson = (s: z.ZodTypeAny): JSONSchema7 => zodToJsonSchema(s) as JSONSchema7const skill = { name: 'coding-feature-flag-reviewer', description: "Feature Flag Reviewer — typed output agent (draft spec).", systemPrompt: `You are Feature Flag Reviewer. Risky flags in PRs. Output: Risk findings typed.Actionable findings citing input sources. No invented issues.NEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.${UNTRUSTED_CONTENT_DIRECTIVE}Call submit_flag_reviewer exactly once. Stop.`, tools: ['submit_flag_reviewer'],}export function createCodingFeatureFlagReviewerAgent(config: CodingFeatureFlagReviewerConfig) { const submit = (): ToolDefinition => defineZodTool({ name: 'submit_flag_reviewer', description: 'Submit result. Once.', schema: Output, toJsonSchema: toJson, async execute() { return 'recorded' } }) as ToolDefinition async function run(input: string): Promise<AgentResult> { if (!input?.trim()) throw new Error('coding-feature-flag-reviewer requires non-empty input') const result = await invokeStructured({ adapter: config.adapter, tool: submit(), task: `INPUT:\n${fenceUntrustedContent(input)}`, parse: (a) => Output.parse(a), skill, memory: config.memory, observers: config.observers, onConfirm: config.onConfirm, maxSteps: config.maxSteps ?? 4, }) return { ...result, requiresReview: true } } return { name: 'coding-feature-flag-reviewer', run, asHandle() { return { name: 'coding-feature-flag-reviewer', run: (t: string) => run(t).then((r) => JSON.stringify(r)) } }, }}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-feature-flag-reviewer', cases: [ { input: 'Complete input for Feature Flag Reviewer: Risky flags in PRs. Provide full structured output.', expected: (r: string) => r.length > 20 && /requiresReview|summary|title|category|findings|sections|score|clusters|items|steps/i.test(r) }, { input: 'Minimal input.', expected: (r: string) => /gap|openQuestion/i.test(r) || r.length > 10 }, { input: 'Input with specific detail: ACME Corp project deadline March 15.', expected: (r: string) => /ACME|March|15/i.test(r) || /gap/i.test(r) }, { input: 'Empty context — only says "process this".', expected: (r: string) => r.length > 5 }, ],}Was this agent useful?
Your response helps us prioritize agent quality.