LangChain / LangGraph Integration#

Integrate FirstOps with LangChain and LangGraph to govern tool-using agents.

Overview#

LangChain agents use tools to interact with external services. FirstOps wraps those tool connections with identity, policy enforcement, credential brokering, and audit logging.

Setup#

1. Create an agent principal#

Create an autonomous agent principal in the FirstOps dashboard. You will receive an agent ID and a DPoP private key PEM.

2. Register connections#

fo connection add --name notion --url https://mcp.notion.com --auth bearer --token ntn_secret_... --agent <agent-name>
fo connection add --name github --url https://mcp.github.com --auth bearer --token ghp_... --agent <agent-name>
fo connection add --name slack --url https://mcp.slack.com --auth bearer --token xoxb_... --agent <agent-name>

3. Install dependencies#

pip install langchain langgraph firstops

4. Configure LangChain tools with FirstOps#

import firstops
from langchain_openai import ChatOpenAI

# Start the FirstOps proxy — handles DPoP authentication per request
firstops.init(
    agent_id="<uuid>",
    private_key_pem=open("key.pem").read(),
)

# Your MCP tool connections go through the FirstOps proxy
# Use the connection IDs from step 2
notion_url = "http://127.0.0.1:9322/mcp/proxy/<notion-conn-id>"
github_url = "http://127.0.0.1:9322/mcp/proxy/<github-conn-id>"
slack_url = "http://127.0.0.1:9322/mcp/proxy/<slack-conn-id>"

# Wire these proxy URLs into your LangChain MCP tool configuration
# The exact integration depends on your LangChain MCP tool setup

# Clean up on shutdown
firstops.shutdown()

LangGraph multi-agent#

For LangGraph workflows with multiple agents, each agent can have its own FirstOps principal. Run each agent as a separate process with its own proxy:

Agent 1 — Research (process 1):

import firstops

firstops.init(agent_id="<research-uuid>", private_key_pem=research_key, port=9322)
notion_url = "http://127.0.0.1:9322/mcp/proxy/<notion-conn-id>"

Agent 2 — Action (process 2):

import firstops

firstops.init(agent_id="<action-uuid>", private_key_pem=action_key, port=9323)
github_url = "http://127.0.0.1:9323/mcp/proxy/<github-conn-id>"

Each agent has independent identity, permissions, and audit trail — even within the same LangGraph workflow.