Guides
Integrating with Anthropic

Integrating with Anthropic

Verify claims in Anthropic (Claude) responses.

Overview

Use GlyphNet to verify factual claims made by Claude models before presenting them to users.

User Query → Anthropic API → Claude Response → GlyphNet Verification → Verified Response

Basic Integration

import anthropic
import requests
 
client = anthropic.Anthropic(api_key="sk-ant-...")
GLYPHNET_API_KEY = "gn_live_..."
 
def chat_with_verification(user_message: str) -> dict:
    # Step 1: Get Claude response
    message = client.messages.create(
        model="claude-3-opus-20240229",
        max_tokens=1024,
        messages=[{"role": "user", "content": user_message}]
    )
    ai_response = message.content[0].text
 
    # Step 2: Verify claims
    verification = requests.post(
        "https://api.glyphnet.io/v1/verify",
        headers={"X-API-Key": GLYPHNET_API_KEY},
        json={"text": ai_response, "mode": "flagging"}
    ).json()
 
    # Step 3: Return with verification status
    return {
        "response": ai_response,
        "verified": not verification["flagged"],
        "claims": verification["claims"],
        "confidence": verification["summary"]["avg_confidence"]
    }

Using Claude's Tool Use

Integrate GlyphNet as a tool that Claude can call:

import anthropic
import requests
import json
 
client = anthropic.Anthropic()
GLYPHNET_API_KEY = "gn_live_..."
 
tools = [
    {
        "name": "verify_facts",
        "description": "Verify factual claims against a knowledge graph. Use this before stating facts.",
        "input_schema": {
            "type": "object",
            "properties": {
                "claims": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "List of factual claims to verify"
                }
            },
            "required": ["claims"]
        }
    }
]
 
def verify_facts(claims: list[str]) -> dict:
    """Verify claims using GlyphNet."""
    results = []
    for claim in claims:
        response = requests.post(
            "https://api.glyphnet.io/v1/verify",
            headers={"X-API-Key": GLYPHNET_API_KEY},
            json={"text": claim}
        ).json()
        results.append({
            "claim": claim,
            "verified": response["claims"][0]["verified"] if response["claims"] else False,
            "confidence": response["claims"][0]["confidence"] if response["claims"] else 0
        })
    return {"results": results}
 
def chat_with_tool_verification(user_message: str) -> str:
    messages = [{"role": "user", "content": user_message}]
 
    while True:
        response = client.messages.create(
            model="claude-3-opus-20240229",
            max_tokens=1024,
            tools=tools,
            messages=messages
        )
 
        # Check if Claude wants to use a tool
        if response.stop_reason == "tool_use":
            tool_use = next(
                block for block in response.content
                if block.type == "tool_use"
            )
 
            if tool_use.name == "verify_facts":
                result = verify_facts(tool_use.input["claims"])
 
                messages.append({"role": "assistant", "content": response.content})
                messages.append({
                    "role": "user",
                    "content": [{
                        "type": "tool_result",
                        "tool_use_id": tool_use.id,
                        "content": json.dumps(result)
                    }]
                })
        else:
            # Final response
            return response.content[0].text

System Prompt for Accuracy

Instruct Claude to be verification-aware:

def chat_accuracy_focused(user_message: str) -> dict:
    message = client.messages.create(
        model="claude-3-opus-20240229",
        max_tokens=1024,
        system="""You are a helpful assistant that prioritizes accuracy.
        - Clearly distinguish between facts and opinions
        - Express uncertainty when you're not sure
        - Stick to well-established information
        - Avoid speculation about recent events""",
        messages=[{"role": "user", "content": user_message}]
    )
 
    ai_response = message.content[0].text
 
    # Verify the response
    verification = requests.post(
        "https://api.glyphnet.io/v1/verify",
        headers={"X-API-Key": GLYPHNET_API_KEY},
        json={"text": ai_response}
    ).json()
 
    return {
        "response": ai_response,
        "verification": verification
    }

Retry Pattern with Corrections

def chat_with_correction(user_message: str, max_retries: int = 2) -> str:
    messages = [{"role": "user", "content": user_message}]
 
    for attempt in range(max_retries + 1):
        response = client.messages.create(
            model="claude-3-opus-20240229",
            max_tokens=1024,
            messages=messages
        )
        ai_response = response.content[0].text
 
        # Verify
        verification = requests.post(
            "https://api.glyphnet.io/v1/verify",
            headers={"X-API-Key": GLYPHNET_API_KEY},
            json={"text": ai_response}
        ).json()
 
        if not verification["flagged"]:
            return ai_response
 
        if attempt < max_retries:
            # Request correction
            unverified = [c for c in verification["claims"] if not c["verified"]]
            messages.append({"role": "assistant", "content": ai_response})
            messages.append({
                "role": "user",
                "content": f"Some claims couldn't be verified: {[c['text'] for c in unverified]}. "
                           "Please revise your response with more accurate information."
            })
 
    # Return with warning if verification failed after retries
    return f"{ai_response}\n\n⚠️ Some claims could not be verified."

Streaming with Post-Verification

async def stream_with_verification(user_message: str):
    full_response = ""
 
    # Stream Claude's response
    with client.messages.stream(
        model="claude-3-opus-20240229",
        max_tokens=1024,
        messages=[{"role": "user", "content": user_message}]
    ) as stream:
        for text in stream.text_stream:
            full_response += text
            yield {"type": "text", "content": text}
 
    # Verify after streaming completes
    verification = requests.post(
        "https://api.glyphnet.io/v1/verify",
        headers={"X-API-Key": GLYPHNET_API_KEY},
        json={"text": full_response}
    ).json()
 
    yield {
        "type": "verification",
        "verified": not verification["flagged"],
        "claims": verification["claims"]
    }

Handling Different Content Types

def process_claude_response(user_message: str) -> dict:
    response = client.messages.create(
        model="claude-3-opus-20240229",
        max_tokens=1024,
        messages=[{"role": "user", "content": user_message}]
    )
 
    results = []
    for block in response.content:
        if block.type == "text":
            # Verify text content
            verification = requests.post(
                "https://api.glyphnet.io/v1/verify",
                headers={"X-API-Key": GLYPHNET_API_KEY},
                json={"text": block.text}
            ).json()
 
            results.append({
                "type": "text",
                "content": block.text,
                "verification": verification
            })
 
    return {"results": results}

Best Practices for Claude Integration

  1. Use tool_use for real-time verification - Let Claude verify as it generates
  2. Set appropriate system prompts - Prime Claude for accuracy
  3. Verify only factual content - Skip opinions and instructions
  4. Handle Claude's uncertainty - It often qualifies statements appropriately
  5. Cache verification results - Same claims don't need re-verification