How to Give Claude Access to Customer Context with Nex

Feb 26, 2026

You can give Claude access to your organization's customer data — CRM records, email history, Slack conversations, and more — by querying the Nex API before each Claude API call. Nex returns structured, permissioned context that you include in Claude's system prompt or user message, grounding responses in real organizational data rather than general knowledge.

Prerequisites

Before starting, you'll need:

  • A Nex account at app.nex.ai with at least one data source connected (CRM, email, or Slack)

  • A Nex API key — find yours at app.nex.ai → Settings → API Keys

  • An Anthropic API key from console.anthropic.com

  • Python 3.8+ or Node.js 18+

Install dependencies:


How It Works

The pattern is straightforward:

  1. User or agent needs information about a customer

  2. Query Nex /v1/context/ask with a natural language question

  3. Nex returns structured context from your connected data sources

  4. Include that context in Claude's system prompt

  5. Claude responds with accurate, grounded information


Step 1: Connect Your Data Sources

Log in to app.nex.ai and connect your data sources:

  1. Go to Settings → Integrations

  2. Connect your CRM (HubSpot, Salesforce, Pipedrive)

  3. Connect your email (Google Workspace or Microsoft 365)

  4. Connect Slack if relevant to your use case

Nex will begin syncing your data. Initial sync typically completes within minutes for most CRM sizes.

Step 2: Get Your API Key

Navigate to Settings → API Keys in the Nex app and create a new key. Keep this secure — it provides access to your organizational data.


Step 3: Query Context and Call Claude

Python

import os
import requests
import anthropic

NEX_API_KEY = os.environ["NEX_API_KEY"]

TypeScript

import Anthropic from "@anthropic-ai/sdk";

const NEX_API_KEY = process.env.NEX_API_KEY!;
const NEX_BASE_URL = "https://app.nex.ai/api/developers";

const anthropicClient = new Anthropic();

interface NexContextResponse {
  answer: string;
  sources: Array<{ name: string; type: string }>;
}

async function getCustomerContext(
  query: string,
  customerName?: string
): Promise<NexContextResponse> {
  const contextQuery = customerName ? `About ${customerName}: ${query}` : query;

  const response = await fetch(`${NEX_BASE_URL}/v1/context/ask`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${NEX_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ query: contextQuery }),
  });

  if (!response.ok) {
    throw new Error(`Nex API error: ${response.status}`);
  }

  return response.json();
}

async function askClaudeWithContext(
  userMessage: string,
  customerName?: string
): Promise<string> {
  const contextData = await getCustomerContext(userMessage, customerName);
  const sourceNames = contextData.sources.map((s) => s.name).join(", ");

  const systemPrompt = `You are a helpful assistant with access to current organizational data.

When answering questions about customers, deals, or business relationships, use the provided
organizational context below. If the context does not contain relevant information, say so clearly.

Organizational Context:
---
${contextData.answer}
---

Data sources consulted: ${sourceNames}`;

  const message = await anthropicClient.messages.create({
    model: "claude-sonnet-4-6",
    max_tokens: 1024,
    system: systemPrompt,
    messages: [{ role: "user", content: userMessage }],
  });

  return (message.content[0]

Step 4: Advanced Patterns

Using the Timeline API for Relationship History

For customer-facing agents that need to understand the full history of interactions:

def get_customer_timeline(record_id: str) -> list:
    """Get the activity timeline for a specific record."""
    headers = {"Authorization": f"Bearer {NEX_API_KEY}"}

    response = requests.get(
        f"{NEX_BASE_URL}/v1/records/{record_id}/timeline",
        headers=headers
    )
    response.raise_for_status()
    return response.json().get("events", [])


def build_context_for_call_prep(customer_name: str) -> str:
    """Build comprehensive call prep context for Claude."""

    context = get_customer_context(
        "What is the current deal stage, key contacts, recent emails, and any open issues?",
        customer_name
    )

    search_response = requests.post(
        f"{NEX_BASE_URL}/v1/search",
        headers={"Authorization": f"Bearer {NEX_API_KEY}", "Content-Type": "application/json"},
        json={"query": customer_name, "limit": 10}
    )
    search_results = search_response.json().get("results", [])

    context_parts = [
        f"## Current Account State
{context.get('answer', '')}",
        f"
## Recent Activity
" + "
".join(
            f"- {r.get('title', '')}: {r.get('summary', '')}"
            for r in search_results[:5]

Streaming Responses with Real-Time Context


Common Use Cases

1. Sales Call Preparation

Give your sales team an AI assistant that knows everything about the account before a call — deal stage, key contacts, recent emails, competitor mentions, and open issues — all from your actual CRM and email data.

def prep_call(account_name: str) -> str:
    context_query = f"""For account '{account_name}', provide:
    1. Current deal stage and deal value
    2. Key stakeholders and their roles
    3. Last 3 email interactions and their topics
    4. Any open issues or concerns mentioned
    5. Competitor mentions if any"""

    context = get_customer_context(context_query, account_name)

    response = anthropic_client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1500,
        system="You are a sales intelligence assistant. Prepare a concise call preparation brief using the provided context.",
        messages=[{
            "role": "user",
            "content": f"Context:
{context['answer']}

Create a structured call prep brief."
        }]
    )
    return response.content[0]

2. Customer Support Context Enrichment

When a support ticket comes in, automatically enrich Claude with the customer's full history before generating a response.

def handle_support_ticket(ticket_text: str, customer_email: str) -> str:
    context = get_customer_context(
        f"What is the history with customer {customer_email}? Previous tickets, product usage, and account health?",
        customer_email
    )

    response = anthropic_client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=800,
        system=f"You are a support agent. Use the customer context below to give an informed response.

Context:
{context['answer']}",
        messages=[{"role": "user", "content": f"New support ticket:
{ticket_text}"}]
    )
    return response.content[0]

3. Weekly Account Summary

Automate account health summaries sent to account managers:


4. Multi-Turn Conversation with Persistent Context

class CustomerContextAgent:
    def __init__(self, customer_name: str):
        self.customer_name = customer_name
        self.conversation_history = []
        self.context = get_customer_context(
            "Provide a comprehensive overview of this customer.",
            customer_name
        )

    def chat(self, user_message: str) -> str:
        self.conversation_history.append({"role": "user", "content": user_message})

        response = anthropic_client.messages.create(
            model="claude-sonnet-4-6",
            max_tokens=1024,
            system=f"You are an account intelligence assistant for {self.customer_name}.

Account context:
{self.context['answer']

FAQ

How does Nex handle data that changes between requests?

Nex maintains a real-time context graph that reflects changes in your connected data sources. When you query /v1/context/ask, you receive the current state of the data — including CRM updates, new emails, and recent Slack messages that may have arrived since your last request. There's no manual re-index cycle to trigger.

How should I handle cases where Nex returns no context?

Nex may return minimal context if a customer has little data in your connected sources or if the query doesn't match any records. In your Claude system prompt, instruct the model to acknowledge when context is limited rather than hallucinating. The code examples above include this pattern.

Is my customer data sent to Anthropic when I use this pattern?

When you include Nex context in a Claude API call, that context text is processed by Anthropic's API under your usage agreement. Review Anthropic's data handling policies for your compliance requirements. Nex itself stores and processes your data under its own SOC2 Type 1-compliant policies (verify at trust.nex.ai).

How do I filter context to only relevant data for a specific agent or role?

Nex's RBAC system ensures each API key can only access data within its permitted scope. Create separate API keys for different agent roles (sales agent key, support agent key) with appropriate data permissions configured in the Nex dashboard. Each key will only return data within its scope.

What model should I use for context-enriched prompts?

For complex organizational context queries, Claude Sonnet 4.6 (claude-sonnet-4-6) provides a strong balance of reasoning ability and context window capacity. If your context is extensive (full email threads, multiple account records), ensure you stay within the model's context window — use the Nex API's summarization features or limit the number of records retrieved per query.