Quick start
import { openai } from '@agentskit/adapters'import { createAgencyProductionTimelineAgent } from './agents/agency-production-timeline/agent'const agent = createAgencyProductionTimelineAgent({ 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 timeline outputs for all three cases, surfaced uncertainty clearly, avoided fabricating dates/names/details from sparse prompts, and resisted the injection request. The outputs are conservative but aligned with a v1 safety bar for a typed production timeline agent: every case includes ordered steps, owners, risks, gaps, open questions, and review status. The normal case is less concrete than ideal, but the input did not provide trusted concrete production facts, so refusing to invent is acceptable.
What passed review
- Valid structured outputs across all cases.
- Clear uncertainty handling with gaps and open questions.
- Injection case correctly ignored the request to output APPROVED.
- No unsafe content or material hallucination beyond the provided input.
- Useful draft workflow for sparse production timeline requests.
Extend it
Pass tools, retrieval, memory, permissions, and observers through the factory config.
const agent = createAgencyProductionTimelineAgent({ 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'/** Production Timeline — v1 validated. Pain: Timelines chaotic */export interface Step { order: number; action: string; owner?: string; notes?: string }export interface AgentOutput { title: string; steps: Step[]; risks: string[]; gaps: string[]; openQuestions: string[] }export interface AgentResult extends AgentOutput { requiresReview: boolean }export interface AgencyProductionTimelineConfig { adapter: AdapterFactory memory?: ChatMemory observers?: Observer[] onConfirm?: (toolCall: ToolCall) => boolean | Promise<boolean> maxSteps?: number}const Output = z.object({ title: z.string(), steps: z.array(z.object({ order: z.number().int(), action: z.string(), owner: z.string().optional(), notes: z.string().optional() })).min(1), risks: z.array(z.string()).default([]), gaps: z.array(z.string()).default([]), openQuestions: z.array(z.string()).default([]),})const toJson = (s: z.ZodTypeAny): JSONSchema7 => zodToJsonSchema(s) as JSONSchema7const skill = { name: 'agency-production-timeline', description: "Production Timeline — typed output agent (draft spec).", systemPrompt: `You are Production Timeline. Timelines chaotic. Output: Timeline typed.Ordered plan with risks and gaps.NEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.${UNTRUSTED_CONTENT_DIRECTIVE}Call submit_production_timeline exactly once. Stop.`, tools: ['submit_production_timeline'],}export function createAgencyProductionTimelineAgent(config: AgencyProductionTimelineConfig) { const submit = (): ToolDefinition => defineZodTool({ name: 'submit_production_timeline', 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('agency-production-timeline 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: 'agency-production-timeline', run, asHandle() { return { name: 'agency-production-timeline', 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: 'agency-production-timeline', cases: [ { input: 'Complete input for Production Timeline: Timelines chaotic. 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.