How to Integrate Anthropic for insurance with pgvector for multi-agent systems

By Cyprian AaronsUpdated 2026-04-21
anthropic-for-insurancepgvectormulti-agent-systems

Combining Anthropic for insurance with pgvector gives you a practical pattern for multi-agent systems that need both reasoning and retrieval. In insurance, that usually means one agent classifies a claim, another retrieves policy clauses or prior similar cases, and a third drafts the response with evidence attached.

The value is simple: Anthropic handles the language and decision-making, while pgvector gives your agents fast semantic search over claims notes, policy docs, underwriting guidelines, and adjuster playbooks.

Prerequisites

  • Python 3.10+
  • PostgreSQL 15+ with the pgvector extension installed
  • An Anthropic API key
  • A Postgres database URL
  • Python packages:
    • anthropic
    • psycopg[binary]
    • pgvector
    • sqlalchemy
    • numpy
  • A corpus of insurance documents:
    • policy wording
    • claims manuals
    • underwriting rules
    • prior case summaries

Install the dependencies:

pip install anthropic psycopg[binary] pgvector sqlalchemy numpy

Integration Steps

  1. Create the vector table in Postgres

Use pgvector to store document embeddings alongside metadata. For insurance systems, keep fields like doc_type, policy_id, claim_id, and jurisdiction so agents can filter before they retrieve.

import psycopg
from pgvector.psycopg import register_vector

conn = psycopg.connect("postgresql://postgres:postgres@localhost:5432/insurance")
register_vector(conn)

with conn.cursor() as cur:
    cur.execute("CREATE EXTENSION IF NOT EXISTS vector;")
    cur.execute("""
        CREATE TABLE IF NOT EXISTS insurance_docs (
            id SERIAL PRIMARY KEY,
            doc_type TEXT NOT NULL,
            source ტექXT NOT NULL,
            metadata JSONB DEFAULT '{}'::jsonb,
            embedding VECTOR(1536)
        );
    """)
    conn.commit()

print("Table ready")

If you are using OpenAI-style embeddings from another service, match the vector dimension to that model. The table schema is what matters here: store text, metadata, and a fixed-size embedding column.

  1. Generate embeddings and store them in pgvector

Anthropic does not provide an embeddings API in the same way some other providers do, so use an embedding model from your stack and keep Anthropic for generation and reasoning. In production, this separation is normal: retrieval model for vectors, Claude for orchestration.

import numpy as np
import psycopg
from pgvector.psycopg import register_vector

def fake_embed(text: str) -> list[float]:
    # Replace with your real embedding provider.
    rng = np.random.default_rng(abs(hash(text)) % (2**32))
    return rng.normal(size=1536).astype(np.float32).tolist()

docs = [
    ("policy", "Coverage applies when damage is sudden and accidental.", {"policy_id": "P-1001"}),
    ("claims_note", "Adjuster observed water ingress from burst pipe.", {"claim_id": "C-7788"}),
]

conn = psycopg.connect("postgresql://postgres:postgres@localhost:5432/insurance")
register_vector(conn)

with conn.cursor() as cur:
    for doc_type, text, metadata in docs:
        emb = fake_embed(text)
        cur.execute(
            """
            INSERT INTO insurance_docs (doc_type, source_text, metadata, embedding)
            VALUES (%s, %s, %s::jsonb, %s)
            """,
            (doc_type, text, json.dumps(metadata), emb),
        )
    conn.commit()

For a real system, replace fake_embed() with your embedding provider. The rest of the pipeline stays the same.

  1. Query pgvector for relevant context

Your retrieval agent should pull the top-k most relevant chunks before calling Claude. This keeps responses grounded in policy text and claim history.

import json
import psycopg
from pgvector.psycopg import register_vector

def retrieve_context(query_embedding: list[float], limit: int = 3):
    conn = psycopg.connect("postgresql://postgres:postgres@localhost:5432/insurance")
    register_vector(conn)

    with conn.cursor() as cur:
        cur.execute(
            """
            SELECT doc_type, source_text, metadata,
                   1 - (embedding <=> %s) AS similarity
            FROM insurance_docs
            ORDER BY embedding <=> %s
            LIMIT %s;
            """,
            (query_embedding, query_embedding, limit),
        )
        return cur.fetchall()

query_emb = fake_embed("Is burst pipe damage covered under this policy?")
matches = retrieve_context(query_emb)

for row in matches:
    print(row)

The important operator here is <=>, which is the cosine distance operator used by pgvector. Lower distance means closer match.

  1. Call Anthropic with retrieved evidence

Use Anthropic’s Messages API to turn retrieved context into a grounded answer. For multi-agent systems, this can be your “claims reasoning” agent or “policy interpretation” agent.

import anthropic

client = anthropic.Anthropic(api_key="YOUR_ANTHROPIC_API_KEY")

context_block = "\n\n".join(
    f"[{doc_type}] {text} | metadata={metadata} | similarity={similarity:.3f}"
    for doc_type, text, metadata, similarity in matches
)

message = client.messages.create(
    model="claude-3-5-sonnet-latest",
    max_tokens=400,
    temperature=0,
    messages=[
        {
            "role": "user",
            "content": f"""
You are an insurance claims assistant.
Answer only using the evidence below.

Evidence:
{context_block}

Question:
Is burst pipe damage covered under this policy?
"""
        }
    ],
)

print(message.content[0].text)

Keep temperature at 0 for claims workflows where determinism matters. Also keep the prompt strict: ask Claude to answer only from evidence so it does not invent coverage language.

  1. Wire it into a multi-agent flow

A practical pattern is one orchestrator agent plus specialized workers:

  • retrieval agent queries pgvector
  • policy agent interprets clauses
  • claims agent drafts response
  • compliance agent checks wording before release
def answer_claim(question: str):
    q_emb = fake_embed(question)
    rows = retrieve_context(q_emb)

    evidence = "\n".join([f"- {r[1]} ({r[0]})" for r in rows])

    resp = client.messages.create(
        model="claude-3-5-sonnet-latest",
        max_tokens=300,
        temperature=0,
        messages=[
            {
                "role": "user",
                "content": f"""
You are a claims triage agent.
Use only these retrieved records:

{evidence}

Question: {question}
Return:
1) coverage assessment
2) cited evidence summary
3) next action for adjuster
"""
            }
        ],
    )
    return resp.content[0].text

print(answer_claim("Does this water damage claim look covered?"))

That structure scales well because each agent has one job. Retrieval stays in Postgres; reasoning stays in Claude.

Testing the Integration

Run an end-to-end check with one known policy clause and one query that should match it.

test_question = "Is sudden accidental water damage covered?"
result = answer_claim(test_question)
print(result)

Expected output:

1) coverage assessment: Likely covered if the loss was sudden and accidental.
2) cited evidence summary: Retrieved policy text states coverage applies when damage is sudden and accidental.
3) next action for adjuster: Confirm cause of loss and check exclusions.

If retrieval returns irrelevant chunks, fix your chunking strategy or add metadata filters before calling Claude.

Real-World Use Cases

  • Claims triage assistant

    • Retrieve similar historical claims from pgvector.
    • Have Claude classify severity, likely coverage position, and required follow-up questions.
  • Policy Q&A copilot

    • Search policy wording by semantic meaning instead of exact keywords.
    • Let Claude answer broker or customer questions with citations from retrieved clauses.
  • Underwriting support agent

    • Pull risk guidelines, prior submissions, and referral rules.
    • Use Claude to draft underwriting notes and flag cases needing human review.

This combo works because it maps cleanly to production responsibilities. Postgres owns data retrieval; Anthropic owns language decisions; your orchestrator owns control flow across agents.


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