Skip to main content
This setup works for both LangChain and LangGraph. The same instrumentation handles both frameworks.

Set TCC environment variables

Our SDKs default to using the TCC_API_KEY environment variable.
.env
TCC_API_KEY="your-api-key"

Instrument LangChain & LangGraph

Step 1: Install dependencies

pip install "contextcompany[langchain]"

Step 2: Add instrumentation

You’ll need to initialize instrumentation before LangChain or LangGraph is imported. This is typically at the top of your application’s entry point (for example, in main.py or app.py).LangChain example:
main.py
import os
from dotenv import load_dotenv
load_dotenv()

# Import and initialize TCC instrumentation BEFORE importing LangChain
from contextcompany.langchain import instrument_langchain

instrument_langchain()

# Your existing LangChain code
from langchain_openai import ChatOpenAI
from langchain.agents import create_openai_functions_agent, AgentExecutor

model = ChatOpenAI(model="gpt-4")
agent = create_openai_functions_agent(model, tools=[])
executor = AgentExecutor(agent=agent, tools=[])
LangGraph example:
main.py
import os
from dotenv import load_dotenv
load_dotenv()

# Import and initialize TCC instrumentation BEFORE importing LangGraph
from contextcompany.langchain import instrument_langchain

instrument_langchain()

# Your existing LangGraph code
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent

model = ChatOpenAI(model="gpt-4")
agent = create_react_agent(model, tools=[])
That’s it! Your app will now be instrumented and any LangChain/LangGraph runs, steps, and tool calls will be viewable in the dashboard.

Adding custom metadata

Custom metadata allows you to add additional properties to your agent runs. This is particularly useful for tying agent runs to your own specific business logic, letting you filter and analyze agent runs by user, organization, feature, or some other dimension.
Custom metadata must be passed as a key-value pair through LangChain/LangGraph’s RunnableConfig as the second argument to invoke():
main.py
result = agent_executor.invoke(
    {"input": "Hello!"},
    {
        "metadata": {
            # e.g. tag this agent run with a user id
            "userId": "4a6b111c-b53a-4d00-a877-67185022ab9e",
        }
    }
)
Agent runs are automatically indexed by your custom metadata fields and can be filtered directly in the dashboard.
The tcc.* namespace is reserved. Only the reserved TCC metadata keys (tcc.runId, tcc.sessionId, tcc.conversational, tcc.agent, tcc.userId, tcc.userName, tcc.orgId, tcc.orgName) are recognized; any other tcc.* keys are ignored. None of them appear in your custom metadata.

Adding user feedback

User feedback allows you to collect score (thumbs up & thumbs down) and text feedback (up to 2000 characters) from end users on your agent runs. This is useful for tracking user satisfaction, identifying problematic responses, and filtering agent runs in the dashboard to focus on positive or negative feedback.

Step 1: Generate and pass a run ID

main.py
import uuid

# Generate a unique run ID (must be a UUID) before your agent execution
run_id = str(uuid.uuid4())

result = agent_executor.invoke(
    {"input": "Hello!"},
    {
        "metadata": {
            "tcc.runId": run_id,  # Pass the run ID in metadata
        }
    }
)

# Return the run_id to your client
return {"result": result, "run_id": run_id}

Step 2: Submit feedback from your client

Store the run_id on your client, then when the user provides feedback, submit it using the submit_feedback function.Both score and text are optional individually, but each request must include at least one of them:score is the thumbs rating. Use only "thumbs_up" or "thumbs_down".text is written feedback from your user, up to 2000 characters.
feedback.py
from contextcompany import submit_feedback

# Submit score and/or text feedback:
submit_feedback(
    run_id=run_id,  # The run ID from your agent execution
    score="thumbs_up",  # Optional thumbs rating: "thumbs_up" or "thumbs_down"
    text="This was a helpful response!",  # Optional written user feedback, up to 2000 characters
)
Agent runs with feedback can be filtered in the dashboard using the feedback filter.

Tracking agent sessions

Agent sessions represent multiple agent runs that are grouped together. The most common use case is tracking entire conversations between a human user and an AI agent in chatbot interfaces.
Agent sessions can be tracked by setting a tcc.sessionId key under metadata.
main.py
session_id = "unique-session-identifier"

result = agent_executor.invoke(
    {"input": "Hello!"},
    {
        "metadata": {
            "tcc.sessionId": session_id,  # Track agent sessions
        }
    }
)
The value of sessionId should be a unique identifier for the agent session. This can be any string, but it’s generally recommended to use a UUID. Agent sessions are automatically indexed and can be filtered directly in the dashboard.

Marking runs as conversational

A conversational run is an agent run that was initiated by a user. Marking a run as conversational tells The Context Company that this run involves direct user interaction. This is important because conversational runs are the only runs monitored for user insights, such as user confusion, frustration, or any other custom insights you want to track. Runs that are not marked as conversational (e.g. background jobs, cron tasks, or internal automations) are excluded from user insight analysis.
Mark a run as conversational by setting tcc.conversational to "true" in metadata:
main.py
result = agent_executor.invoke(
    {"input": "Hello!"},
    {
        "metadata": {
            "tcc.conversational": "true",
        }
    }
)

Identifying the agent

If your product ships more than one named agent, set the reserved tcc.agent metadata key to scope the run to a specific agent. The dashboard’s top-level agent selector, per-agent patterns and recaps, and the agent filter on the REST API and MCP tools all read from this key.
main.py
from langchain_openai import ChatOpenAI

model = ChatOpenAI(model="gpt-4")
result = model.invoke(
    "Hello!",
    config={
        "metadata": {
            "tcc.agent": "support-agent",
        }
    }
)
Agent names that collide with reserved dashboard routes (for example runs, sessions, patterns, recaps, overview, search, failures, feedback, tools, topics, views, settings, mcp-and-api) are dropped.

Identifying users and organizations

Attach the end user and their organization to a run as first-class identity using the reserved tcc.userId, tcc.userName, tcc.orgId, and tcc.orgName metadata keys. This is not the same as adding a userId field to custom metadata — these keys promote user and org identity to dedicated dashboard filters and unlock native user/org search, per-user views, and per-org analytics. See User and organization identity for the full concept. Set these whenever you have a stable identifier for the end user or their organization in your product.
main.py
from langchain_openai import ChatOpenAI

model = ChatOpenAI(model="gpt-4")
result = model.invoke(
    "Hello!",
    config={
        "metadata": {
            "tcc.userId": "user-123",
            "tcc.userName": "Jane Doe",
            "tcc.orgId": "org-456",
            "tcc.orgName": "Acme Inc.",
        }
    }
)
tcc.userName and tcc.orgName require the corresponding ID (tcc.userId / tcc.orgId) to also be set. Names without IDs are dropped.

Combining multiple options (TypeScript)

You can combine all TCC options in a single invocation. TCC-specific config goes under the tcc key, while all other keys in the metadata object are automatically tracked as custom metadata on the run:
main.ts
import { ChatOpenAI } from "@langchain/openai";
import { randomUUID } from "crypto";

const model = new ChatOpenAI({ model: "gpt-4" });

const result = await model.invoke("Hello!", {
  metadata: {
    tcc: {
      sessionId: "session-abc-123",
      conversational: true,
      runId: randomUUID(),
      agent: "support-agent",
      userId: "user-123",
      userName: "Jane Doe",
      orgId: "org-456",
      orgName: "Acme Inc.",
    },
    // Custom metadata (tracked automatically)
    feature: "booking",
    environment: "production",
  },
});
KeyTypeDescription
tcc.sessionIdstringSession ID for grouping runs
tcc.conversationalbooleanWhether this run involves user interaction
tcc.runIdstringCustom run ID for feedback tracking
tcc.agentstringAgent name for first-class agent filtering
tcc.userIdstringEnd user’s ID. Required if setting tcc.userName.
tcc.userNamestringEnd user’s display name. Ignored unless tcc.userId is also set.
tcc.orgIdstringEnd user’s organization ID. Required if setting tcc.orgName.
tcc.orgNamestringOrganization display name. Ignored unless tcc.orgId is also set.
Other keysunknownCustom metadata for filtering (tracked automatically)

Debug mode (TypeScript only)

You can enable debug mode in TypeScript to log spans as they are created and exported:
main.ts
import { TCCCallbackHandler } from "@contextcompany/langchain";

const handler = new TCCCallbackHandler({
  debug: true,
});

Examples

See our examples repository for more detailed usage examples.