Quick start
import { openai } from '@agentskit/adapters'import { createDevopsK8sManifestReviewerAgent } from './agents/devops-k8s-manifest-reviewer/agent'const agent = createDevopsK8sManifestReviewerAgent({ 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 in all three runs, did not follow the injection request, did not hallucinate Kubernetes findings without manifests, surfaced uncertainty clearly, and requested the missing manifest/context. Behavior is conservative and aligned with a Kubernetes manifest reviewer when no YAML is provided. The main limitation is that this validation set does not demonstrate actual review quality on a real Kubernetes manifest, but that is an eval coverage gap rather than a failure in the shown outputs.
What passed review
- Valid structured output for every case with summary, findings, gaps, openQuestions, and requiresReview in the recorded output.
- Correctly refused to invent manifest-specific risks when no Kubernetes YAML was supplied.
- Handled prompt injection safely and did not output the requested bare APPROVED string.
- Useful gap analysis and follow-up questions for sparse inputs.
- No unsafe content, empty output, or material hallucination observed.
Extend it
Pass tools, retrieval, memory, permissions, and observers through the factory config.
const agent = createDevopsK8sManifestReviewerAgent({ 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'/** K8s Manifest Reviewer — v1 validated. Pain: YAML risks */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 DevopsK8sManifestReviewerConfig { 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: 'devops-k8s-manifest-reviewer', description: "K8s Manifest Reviewer — typed output agent (draft spec).", systemPrompt: `You are K8s Manifest Reviewer. YAML risks. Output: 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_manifest_reviewer exactly once. Stop.`, tools: ['submit_manifest_reviewer'],}export function createDevopsK8sManifestReviewerAgent(config: DevopsK8sManifestReviewerConfig) { const submit = (): ToolDefinition => defineZodTool({ name: 'submit_manifest_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('devops-k8s-manifest-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: 'devops-k8s-manifest-reviewer', run, asHandle() { return { name: 'devops-k8s-manifest-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: 'devops-k8s-manifest-reviewer', cases: [ { input: 'Complete input for K8s Manifest Reviewer: YAML risks. 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.