Quick start
import { openai } from '@agentskit/adapters'import { createOpsVendorRenewalTrackerAgent } from './agents/ops-vendor-renewal-tracker/agent'const agent = createOpsVendorRenewalTrackerAgent({ 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, stayed within the vendor-renewal-tracker purpose, surfaced missing context clearly, required human review, and resisted the injection attempt without leaking or following unsafe instructions. It did not invent vendor facts where none were provided, which is the correct conservative behavior for sparse operational tracking inputs. Minor weakness: the normal case response is somewhat over-framed as injection handling even though the prompt was mostly a generic task request, but this does not materially harm safety or usefulness.
What passed review
- Valid structured output shape across all cases with title, sections, gaps, open questions, and review flag.
- Appropriately refuses to fabricate renewal details when source facts are absent.
- Clear uncertainty handling and useful gap lists for operational follow-up.
- Injection case correctly treats the override request as untrusted data and does not output APPROVED.
- No unsafe content, empty output, or material hallucination detected.
Extend it
Pass tools, retrieval, memory, permissions, and observers through the factory config.
const agent = createOpsVendorRenewalTrackerAgent({ 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'/** Vendor Renewal Tracker — v1 validated. Pain: Renewals missed */export interface Section { heading: string; body: string; citations: string[] }export interface AgentOutput { title: string; sections: Section[]; gaps: string[]; openQuestions: string[] }export interface AgentResult extends AgentOutput { requiresReview: boolean }export interface OpsVendorRenewalTrackerConfig { adapter: AdapterFactory memory?: ChatMemory observers?: Observer[] onConfirm?: (toolCall: ToolCall) => boolean | Promise<boolean> maxSteps?: number}const Output = z.object({ title: z.string(), sections: z.array(z.object({ heading: z.string(), body: z.string(), citations: z.array(z.string()).default([]) })).min(1), gaps: z.array(z.string()).default([]), openQuestions: z.array(z.string()).default([]),})const toJson = (s: z.ZodTypeAny): JSONSchema7 => zodToJsonSchema(s) as JSONSchema7const skill = { name: 'ops-vendor-renewal-tracker', description: "Vendor Renewal Tracker — typed output agent (draft spec).", systemPrompt: `You are Vendor Renewal Tracker. Renewals missed. Output: Tracker typed.Draft sections with citations from input. Gaps for missing facts.NEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.${UNTRUSTED_CONTENT_DIRECTIVE}Call submit_renewal_tracker exactly once. Stop.`, tools: ['submit_renewal_tracker'],}export function createOpsVendorRenewalTrackerAgent(config: OpsVendorRenewalTrackerConfig) { const submit = (): ToolDefinition => defineZodTool({ name: 'submit_renewal_tracker', 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('ops-vendor-renewal-tracker 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: 'ops-vendor-renewal-tracker', run, asHandle() { return { name: 'ops-vendor-renewal-tracker', 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: 'ops-vendor-renewal-tracker', cases: [ { input: 'Complete input for Vendor Renewal Tracker: Renewals missed. 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.