How to Build a KYC verification Agent Using AutoGen in TypeScript for payments

By Cyprian AaronsUpdated 2026-04-21
kyc-verificationautogentypescriptpayments

A KYC verification agent for payments takes a customer’s identity package, checks it against policy, and decides whether the onboarding flow can continue, needs manual review, or must be rejected. In payments, that matters because bad KYC creates compliance risk, chargeback exposure, and account fraud; good KYC keeps your onboarding fast without letting regulated money move through bad identities.

Architecture

A production KYC agent for payments usually needs these components:

  • Orchestrator agent
    • Owns the workflow and decides which specialist to call next.
  • Document extraction tool
    • Pulls structured fields from passport, national ID, proof of address, and business registration docs.
  • Policy/rules engine
    • Enforces jurisdiction-specific checks like sanctions screening flags, age thresholds, address consistency, and document freshness.
  • Risk scorer
    • Produces a deterministic risk score from the extracted data and external signals.
  • Human review handoff
    • Escalates borderline cases to ops/compliance with a complete audit trail.
  • Audit logger
    • Persists every model output, tool call, and decision for regulators and internal controls.

Implementation

1) Install AutoGen and define the workflow shape

For TypeScript, use the AutoGen SDK with a group chat pattern. The orchestrator coordinates specialized agents instead of letting one model guess everything.

npm install @autogen/agentchat openai zod

Create a small set of typed inputs so your agent stays deterministic around payment compliance fields.

import { config } from "dotenv";
import { z } from "zod";
import { OpenAIChatCompletionClient } from "@autogen/agentchat";
import {
  AssistantAgent,
  UserProxyAgent,
  GroupChat,
  GroupChatManager,
} from "@autogen/agentchat";

config();

const KycInputSchema = z.object({
  fullName: z.string(),
  dateOfBirth: z.string(),
  countryOfResidence: z.string(),
  documentType: z.enum(["passport", "national_id", "driver_license", "utility_bill"]),
  documentNumber: z.string().optional(),
  address: z.string().optional(),
});

type KycInput = z.infer<typeof KycInputSchema>;

2) Build specialist agents with explicit roles

Keep the LLM narrow. One agent extracts facts, another applies policy, and the orchestrator decides whether to approve or escalate.

const client = new OpenAIChatCompletionClient({
  model: "gpt-4o-mini",
  apiKey: process.env.OPENAI_API_KEY!,
});

const extractor = new AssistantAgent({
  name: "extractor",
  modelClient: client,
  systemMessage:
    "Extract KYC facts only. Return concise JSON. Do not approve or reject.",
});

const compliance = new AssistantAgent({
  name: "compliance",
  modelClient: client,
  systemMessage:
    "Apply payment KYC policy. Focus on sanctions risk indicators, document completeness, jurisdiction rules, and auditability. Return one of APPROVE, REVIEW, or REJECT with reasons.",
});

const reviewer = new UserProxyAgent({
  name: "human_reviewer",
});

3) Run the multi-agent review flow

This pattern is simple enough to ship but still gives you an auditable path. The orchestrator passes the customer package through extraction first, then policy review.

async function runKycReview(input: KycInput) {
  const validated = KycInputSchema.parse(input);

  const groupChat = new GroupChat({
    agents: [extractor, compliance],
    messages: [],
    maxRound: 4,
    speakerSelectionMethod: "round_robin",
  });

  const manager = new GroupChatManager({
    groupChat,
    modelClient: client,
    systemMessage:
      "Coordinate a KYC verification workflow for payments. Ensure every decision is explainable and suitable for audit.",
  });

  const prompt = `
KYC application:
${JSON.stringify(validated)}

Step 1: extractor returns structured facts.
Step 2: compliance returns APPROVE, REVIEW, or REJECT with reasons.
`;

  const result = await manager.run(prompt);
  return result;
}

runKycReview({
  fullName: "Jane Doe",
  dateOfBirth: "1991-05-14",
  countryOfResidence: "GB",
  documentType: "passport",
}).then(console.log);

If you need a human-in-the-loop checkpoint for borderline cases, route REVIEW outcomes into an ops queue instead of auto-continuing.

4) Add deterministic guardrails around the LLM output

Payments teams should not let free-form text drive decisions. Parse outputs into a schema before you persist or act on them.

const DecisionSchema = z.object({
  decision: z.enum(["APPROVE", "REVIEW", "REJECT"]),
  reasons: z.array(z.string()).min(1),
});

function normalizeDecision(rawText: string) {
	const parsed = JSON.parse(rawText);
	return DecisionSchema.parse(parsed);
}

In practice, wrap the final assistant response in strict JSON instructions and reject anything that fails validation. That keeps your ledger-facing systems from consuming malformed model output.

Production Considerations

  • Deploy in-region

    Keep customer PII in the same jurisdiction as your payment stack when possible. If you serve EU customers, make sure storage, logs, and vector indexes respect data residency requirements.

  • Log for audit, not for curiosity

    Persist input hashes, extracted fields, tool calls, timestamps, model version, and final decisions. Regulators care about reproducibility; your ops team cares about incident reconstruction.

  • Use hard guardrails before any downstream action

    Never let the agent open an account or enable payouts directly. Require a policy service to confirm APPROVE before provisioning payment rails.

  • Monitor false positives by segment

    Track rejection rates by country, document type, device fingerprint confidence, and manual-review overturn rate. A spike in one corridor usually means either policy drift or a broken upstream verifier.

Common Pitfalls

  • Letting the LLM make compliance policy

    Don’t ask the model to invent KYC thresholds. Put jurisdiction rules in code or a policy service; use the agent to interpret evidence against those rules.

  • Skipping schema validation

    Free-form text will eventually break your pipeline. Validate every response with Zod before writing to your case store or triggering onboarding.

  • Ignoring audit requirements

    If you cannot explain why an applicant was approved or rejected six months later, you do not have a production KYC system. Store prompts, outputs, versions of policy rules, and reviewer overrides.


Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides