Documentation Index Fetch the complete documentation index at: https://docs.civic.com/llms.txt
Use this file to discover all available pages before exploring further.
Connect a LangGraph agent to Civic using the langchain-mcp-adapters package, which bridges LangGraph’s tool interface with Civic’s Streamable HTTP MCP transport.
Prerequisites
Python 3.11+
A Civic account at app.civic.com with a configured toolkit
A Civic token (generate from Install → MCP URL )
An LLM API key (e.g. Anthropic)
Installation
pip install langgraph langchain-anthropic langchain-mcp-adapters
Environment Variables
# Your full Civic toolkit URL (include profile param for production agents)
CIVIC_URL = https://app.civic.com/hub/mcp? profile = your-toolkit
# Civic token generated from app.civic.com → Install → MCP URL
CIVIC_TOKEN = your-civic-token
# Your LLM provider key
ANTHROPIC_API_KEY = your-anthropic-key
Get Your Credentials How to generate a Civic token and configure toolkit URL parameters
Connecting to Civic
Use MultiServerMCPClient to connect your agent to the Civic MCP Hub over Streamable HTTP, then pass the discovered tools to your LangGraph graph:
import os
from langchain_anthropic import ChatAnthropic
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import MessagesState, StateGraph, START
from langgraph.prebuilt import ToolNode, tools_condition
async def create_agent ():
client = MultiServerMCPClient({
"civic-nexus" : {
"transport" : "streamable_http" ,
"url" : os.environ[ "CIVIC_URL" ],
"headers" : { "Authorization" : f "Bearer { os.environ[ 'CIVIC_TOKEN' ] } " },
}
})
tools = await client.get_tools()
model = ChatAnthropic( model = "claude-sonnet-4-5" ).bind_tools(tools)
def call_model ( state : MessagesState):
return { "messages" : [model.invoke(state[ "messages" ])]}
graph = (
StateGraph(MessagesState)
.add_node( "agent" , call_model)
.add_node( "tools" , ToolNode(tools))
.add_edge( START , "agent" )
.add_conditional_edges( "agent" , tools_condition)
.add_edge( "tools" , "agent" )
.compile( checkpointer = MemorySaver())
)
return graph
Running the Agent
import asyncio
async def main ():
agent = await create_agent()
config = { "configurable" : { "thread_id" : "session-1" }}
result = await agent.ainvoke(
{ "messages" : [{ "role" : "user" , "content" : "What events do I have today?" }]},
config = config
)
print (result[ "messages" ][ - 1 ].content)
asyncio.run(main())
Production Configuration
For production agents, always lock to a specific toolkit using the profile URL parameter:
CIVIC_URL = https://app.civic.com/hub/mcp? profile = your-production-toolkit
When a profile is specified, the session is locked by default — the agent cannot switch toolkits or modify its own guardrails. This prevents prompt injection attacks from escaping the defined tool scope.
Multi-Account Setup
For organization accounts, include the accountId parameter:
CIVIC_URL = https://app.civic.com/hub/mcp? profile = support & accountId = org_abc123
Pre-load Skills
Load specific Skills at session start using the skills parameter:
CIVIC_URL = https://app.civic.com/hub/mcp? profile = support & skills = escalation,canned-responses
Environment Variable Reference
Variable Description CIVIC_URLFull Civic toolkit URL including profile and any URL parameters CIVIC_TOKENCivic token from app.civic.com → Install → MCP URL
Reference Implementation
A complete reference implementation including a FastAPI chat UI, streaming responses, and production patterns is available at:
github.com/civicteam/langchain-nexus-reference-implementation
Next Steps
Agent Deployment Production deployment guide: profile locking, URL params, authentication
Guardrails Constrain what tools your LangGraph agent can use
Audit Trail Query what your agent did via Civic Chat
Get Credentials Token generation and URL parameter reference