{"id":"data-lineage-tracer","title":"Lineage Tracer","description":"Lineage typed. Lineage unknown. Typed v1 agent with eval coverage.","category":"data","status":"validated","version":"1.0.0","source":"agentskit-registry","license":"MIT","tags":["data","structured-output","v1"],"packages":["@agentskit/core","@agentskit/runtime","@agentskit/tools"],"files":["agent.ts","README.md","eval.ts"],"requires":{"zod":"^3","zod-to-json-schema":"^3"},"skill":{"name":"data-lineage-tracer","description":"Lineage typed. Lineage unknown. Typed v1 agent with eval coverage.","systemPrompt":"You are Lineage Tracer. Lineage unknown. Output: Lineage typed.\nDraft sections with citations from input. Gaps for missing facts.\nNEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.\n${UNTRUSTED_CONTENT_DIRECTIVE}\nCall submit_lineage_tracer exactly once. Stop."},"flow":null,"a2a":{"id":"io.agentskit.registry.data-lineage-tracer","name":"Lineage Tracer","description":"Lineage typed. Lineage unknown. Typed v1 agent with eval coverage.","version":"1.0.0","homepage":"https://registry.agentskit.io","skills":[{"name":"data-lineage-tracer","description":"Lineage typed. Lineage unknown. Typed v1 agent with eval coverage.","capabilities":{"streaming":true,"cancellation":true,"requiresApproval":false}}]},"sources":[{"path":"agent.ts","content":"import type { AdapterFactory, ChatMemory, Observer, ToolCall, ToolDefinition } from '@agentskit/core'\nimport { fenceUntrustedContent, UNTRUSTED_CONTENT_DIRECTIVE } from '@agentskit/core/security'\nimport { invokeStructured } from '@agentskit/runtime'\nimport { defineZodTool } from '@agentskit/tools'\nimport { z } from 'zod'\nimport { zodToJsonSchema } from 'zod-to-json-schema'\nimport type { JSONSchema7 } from 'json-schema'\n\n/** Lineage Tracer — v1 validated. Pain: Lineage unknown */\n\nexport interface Section { heading: string; body: string; citations: string[] }\nexport interface AgentOutput { title: string; sections: Section[]; gaps: string[]; openQuestions: string[] }\nexport interface AgentResult extends AgentOutput { requiresReview: boolean }\nexport interface DataLineageTracerConfig {\n  adapter: AdapterFactory\n  memory?: ChatMemory\n  observers?: Observer[]\n  onConfirm?: (toolCall: ToolCall) => boolean | Promise<boolean>\n  maxSteps?: number\n}\n\nconst Output = z.object({\n  title: z.string(),\n  sections: z.array(z.object({ heading: z.string(), body: z.string(), citations: z.array(z.string()).default([]) })).min(1),\n  gaps: z.array(z.string()).default([]),\n  openQuestions: z.array(z.string()).default([]),\n})\nconst toJson = (s: z.ZodTypeAny): JSONSchema7 => zodToJsonSchema(s) as JSONSchema7\n\nconst skill = {\n  name: 'data-lineage-tracer',\n  description: \"Lineage Tracer — typed output agent (draft spec).\",\n  systemPrompt: `You are Lineage Tracer. Lineage unknown. Output: Lineage typed.\nDraft sections with citations from input. Gaps for missing facts.\nNEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.\n${UNTRUSTED_CONTENT_DIRECTIVE}\nCall submit_lineage_tracer exactly once. Stop.`,\n  tools: ['submit_lineage_tracer'],\n}\n\nexport function createDataLineageTracerAgent(config: DataLineageTracerConfig) {\n  const submit = (): ToolDefinition =>\n    defineZodTool({ name: 'submit_lineage_tracer', description: 'Submit result. Once.', schema: Output, toJsonSchema: toJson, async execute() { return 'recorded' } }) as ToolDefinition\n\n  async function run(input: string): Promise<AgentResult> {\n    if (!input?.trim()) throw new Error('data-lineage-tracer requires non-empty input')\n    const result = await invokeStructured({\n      adapter: config.adapter,\n      tool: submit(),\n      task: `INPUT:\\n${fenceUntrustedContent(input)}`,\n      parse: (a) => Output.parse(a),\n      skill,\n      memory: config.memory,\n      observers: config.observers,\n      onConfirm: config.onConfirm,\n      maxSteps: config.maxSteps ?? 4,\n    })\n    return { ...result, requiresReview: true }\n  }\n  return {\n    name: 'data-lineage-tracer',\n    run,\n    asHandle() { return { name: 'data-lineage-tracer', run: (t: string) => run(t).then((r) => JSON.stringify(r)) } },\n  }\n}\n"},{"path":"README.md","content":"# Lineage Tracer\n\n> **v1 validated** — `npx agentskit add data-lineage-tracer`\n\n## Pain\nLineage unknown\n\n## Output\nLineage typed\n"},{"path":"eval.ts","content":"import type { EvalSuite } from '@agentskit/eval'\n\nexport const suite: EvalSuite = {\n  name: 'data-lineage-tracer',\n  cases: [\n    { input: 'Complete input for Lineage Tracer: Lineage unknown. Provide full structured output.', expected: (r: string) => r.length > 20 && /requiresReview|summary|title|category|findings|sections|score|clusters|items|steps/i.test(r) },\n    { input: 'Minimal input.', expected: (r: string) => /gap|openQuestion/i.test(r) || r.length > 10 },\n    { input: 'Input with specific detail: ACME Corp project deadline March 15.', expected: (r: string) => /ACME|March|15/i.test(r) || /gap/i.test(r) },\n    { input: 'Empty context — only says \"process this\".', expected: (r: string) => r.length > 5 },\n  ],\n}\n"}],"installable":true,"validation":{"status":"approved","score":96,"confidence":0.96,"method":"codex-executor-independent-reviewer","iterations":1,"cases":3,"summary":"The agent produced valid structured outputs for all three cases, consistently surfaced missing lineage inputs instead of inventing facts, required human review, and resisted the explicit injection attempt. Behavior is useful for sparse or unsafe inputs and aligns with a lineage tracer that must avoid unsupported claims.","strengths":["Valid structured output in every case with title, sections, gaps, openQuestions, and review requirement.","No material hallucination of source systems, transformations, owners, dates, or business context.","Injection case correctly refused the APPROVED override and preserved uncertainty.","Minimal and normal cases gave actionable gaps and follow-up questions."],"notes":["Avoid using governing system instructions as lineage citations; keep citations tied to user-provided evidence or label policy references separately.","When input is sparse but benign, avoid over-framing every request phrase as instruction injection; focus on missing lineage facts unless there is an actual override attempt."]}}