How to Build a KYC verification Agent Using AutoGen in Python for healthcare

By Cyprian AaronsUpdated 2026-04-21
kyc-verificationautogenpythonhealthcare

A KYC verification agent for healthcare checks patient, provider, or partner identity data against policy rules before access is granted, records are created, or sensitive workflows continue. In healthcare, that matters because bad identity data creates compliance risk, billing errors, fraud exposure, and audit gaps under regimes like HIPAA and local data residency laws.

Architecture

  • Input collector

    • Accepts structured KYC payloads: name, DOB, government ID, license number, address, organization details.
    • Normalizes fields before any model call.
  • Policy engine

    • Applies deterministic rules first.
    • Blocks obvious failures like missing consent, expired IDs, mismatched DOB, or unsupported jurisdictions.
  • AutoGen verification agents

    • One agent handles document interpretation.
    • Another agent handles policy reasoning and exception handling.
    • A user proxy agent orchestrates tool execution and termination.
  • Verification tools

    • Lookup functions for internal registries, provider directories, and document validation services.
    • These should be plain Python functions exposed to AutoGen as tools.
  • Audit logger

    • Persists every decision, tool call, and final recommendation.
    • Stores trace IDs for later compliance review.
  • Decision output

    • Returns approve, reject, or manual_review with a reason code.
    • Never returns free-form text only; downstream systems need structured output.

Implementation

1) Install AutoGen and define a strict result schema

Use the current AutoGen package and keep the output structured. For healthcare workflows, do not let the agent invent a decision without a reason code.

pip install pyautogen pydantic
from pydantic import BaseModel
from typing import Literal, Optional

class KYCResult(BaseModel):
    decision: Literal["approve", "reject", "manual_review"]
    reason_code: str
    notes: Optional[str] = None

2) Build deterministic validation tools first

These tools should do the boring but important work. The LLM should interpret edge cases, not replace your validation layer.

from datetime import date
from typing import Dict

def validate_required_fields(payload: Dict) -> str:
    required = ["full_name", "date_of_birth", "id_number", "jurisdiction", "consent"]
    missing = [f for f in required if not payload.get(f)]
    if missing:
        return f"missing_fields:{','.join(missing)}"
    if payload["consent"] is not True:
        return "consent_missing"
    return "ok"

def validate_age(payload: Dict) -> str:
    dob = date.fromisoformat(payload["date_of_birth"])
    today = date.today()
    age = today.year - dob.year - ((today.month, today.day) < (dob.month, dob.day))
    if age < 18:
        return "underage"
    return "ok"

def validate_jurisdiction(payload: Dict) -> str:
    allowed = {"US", "CA", "GB"}
    if payload.get("jurisdiction") not in allowed:
        return "unsupported_jurisdiction"
    return "ok"

3) Create AutoGen agents and wire them together

This pattern uses AssistantAgent for reasoning and UserProxyAgent to execute the workflow. The user proxy can call your tools through register_function, then feed results back into the assistant.

import os
from autogen import AssistantAgent, UserProxyAgent

llm_config = {
    "model": os.getenv("OPENAI_MODEL", "gpt-4o-mini"),
    "api_key": os.environ["OPENAI_API_KEY"],
}

verifier = AssistantAgent(
    name="kyc_verifier",
    llm_config=llm_config,
    system_message=(
        "You verify healthcare KYC records. "
        "Use only provided tool outputs and policy rules. "
        "Return one of approve/reject/manual_review with a reason code."
    ),
)

orchestrator = UserProxyAgent(
    name="kyc_orchestrator",
    human_input_mode="NEVER",
    max_consecutive_auto_reply=3,
)

# Example tool wrappers
def run_checks(payload):
    results = {
        "required_fields": validate_required_fields(payload),
        "age": validate_age(payload),
        "jurisdiction": validate_jurisdiction(payload),
    }
    return results

orchestrator.register_function(
    function_map={"run_checks": run_checks}
)

payload = {
    "full_name": "Jane Doe",
    "date_of_birth": "1988-04-12",
    "id_number": "A1234567",
    "jurisdiction": "US",
    "consent": True,
}

message = f"""
Run kyc verification on this healthcare record:
{payload}

Call run_checks(payload), then decide using these rules:
- any failed required field => reject
- underage => reject
- unsupported jurisdiction => manual_review
- otherwise approve
"""

result = orchestrator.initiate_chat(
    verifier,
    message=message,
)
print(result)

4) Force structured decisions and persist an audit trail

In production you want a machine-readable result plus an audit record. Keep the final output separate from the explanation so your EHR or IAM layer can consume it safely.

import json
from datetime import datetime

def audit_event(trace_id: str, payload: dict, decision: dict):
    record = {
        "trace_id": trace_id,
        "timestamp": datetime.utcnow().isoformat(),
        "payload_hash": hash(json.dumps(payload, sort_keys=True)),
        "decision": decision,
        "system": "healthcare_kyc_agent",
    }
    print(json.dumps(record))

# Example final decision object from downstream parsing/validation
decision = {
    "decision": "manual_review",
    "reason_code": "unsupported_jurisdiction",
}
audit_event("trace-001", payload, decision)

If you want stronger control over model output, parse the assistant response into KYCResult before accepting it. Reject anything that does not match the schema.

Production Considerations

  • Compliance by design

    • Treat all identity data as sensitive health-adjacent data.
    • Minimize what goes into prompts.
    • Redact ID numbers where possible and never send raw documents unless your legal review allows it.
  • Data residency

    • Keep processing inside approved regions.
    • If you operate across states or countries, route requests to region-specific deployments.
    • Log where each verification ran so auditors can prove residency controls.
  • Monitoring

    • Track approval rate, manual review rate, false rejects, and tool failure rate.
    • Alert on sudden shifts by jurisdiction or document type.
    • Capture every model version used in each decision.
  • Guardrails

    • Deterministic checks must run before any LLM call.
    • Block free-form approvals if required fields fail.
    • Require human review for edge cases like minors, foreign IDs, or conflicting registry data.

Common Pitfalls

  1. Letting the LLM make the first pass

    • Bad idea. It increases hallucination risk and makes audits messy.
    • Fix it by running hard validation rules before calling AutoGen.
  2. Sending raw PHI or full ID images into prompts

    • That expands your compliance surface fast.
    • Fix it by redacting fields and passing only the minimum metadata needed for verification.
  3. Accepting unstructured model output

    • A paragraph saying “looks good” is not a decision artifact.
    • Fix it by enforcing a schema like KYCResult and rejecting anything that does not parse cleanly.
  4. Ignoring jurisdiction-specific rules

    • Healthcare identity workflows differ across regions and payer contracts.
    • Fix it by encoding region-aware policies in your tool layer and routing ambiguous cases to manual review.

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