home / skills / rshvr / unofficial-cohere-best-practices / cohere-langgraph

cohere-langgraph skill

/skills/cohere-langgraph

This skill provides Cohere LangGraph guided best practices for building and memory-aware ReAct agents with multi-tool workflows.

npx playbooks add skill rshvr/unofficial-cohere-best-practices --skill cohere-langgraph

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
6.5 KB
---
name: cohere-langgraph
description: Cohere LangGraph agents reference for building ReAct agents, multi-tool workflows, agents with memory, and human-in-the-loop patterns. Covers both prebuilt and custom agent architectures.
---

# Cohere LangGraph Agents Reference

## Official Resources

- **Docs & Cookbooks**: https://github.com/cohere-ai/cohere-developer-experience
- **API Reference**: https://docs.cohere.com/reference/about

## Installation

```bash
pip install langgraph langchain-cohere langchain
```

## Cohere ReAct Agent (Prebuilt)

```python
from langchain_cohere import ChatCohere, create_cohere_react_agent
from langchain_core.prompts import ChatPromptTemplate
from langchain.agents import AgentExecutor
from langchain_core.tools import tool

@tool
def get_weather(location: str) -> str:
    """Get current weather for a location."""
    return f"Weather in {location}: 22°C, partly cloudy"

@tool
def calculate(expression: str) -> str:
    """Evaluate a mathematical expression safely."""
    # In production, use a safe math parser like numexpr or sympy
    import ast
    try:
        # Only allow simple math operations
        tree = ast.parse(expression, mode='eval')
        return str(compile(tree, '<string>', 'eval'))
    except:
        return "Error: invalid expression"

llm = ChatCohere(model="command-a-03-2025")
tools = [get_weather, calculate]
prompt = ChatPromptTemplate.from_template("{input}")

agent = create_cohere_react_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True, max_iterations=10)

result = executor.invoke({"input": "What's the weather in Tokyo?"})
print(result["output"])
```

### When to Use Which Agent

**Use `create_cohere_react_agent` when:**
- Complex multi-step tasks
- Using Cohere-specific features (citations, connectors)
- Better token efficiency on long reasoning chains

**Generic `create_react_agent` is fine when:**
- Simple tool-calling workflows
- You want consistent behavior across providers

```python
# Cohere-specific
from langchain_cohere import create_cohere_react_agent
agent = create_cohere_react_agent(llm, tools, prompt)

# Generic (provider-agnostic)
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(llm, tools)
```

## Custom ReAct Agent with LangGraph

```python
from typing import Annotated, Sequence, TypedDict
from langchain_core.messages import BaseMessage, HumanMessage
from langchain_cohere import ChatCohere
from langgraph.graph import StateGraph, END
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode, tools_condition

class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], add_messages]

llm = ChatCohere(model="command-a-03-2025")
tools = [get_weather, calculate]
llm_with_tools = llm.bind_tools(tools)

def call_model(state: AgentState):
    response = llm_with_tools.invoke(state["messages"])
    return {"messages": [response]}

workflow = StateGraph(AgentState)
workflow.add_node("agent", call_model)
workflow.add_node("tools", ToolNode(tools))
workflow.set_entry_point("agent")
workflow.add_conditional_edges("agent", tools_condition, {"tools": "tools", "__end__": END})
workflow.add_edge("tools", "agent")

app = workflow.compile()

result = app.invoke({"messages": [HumanMessage(content="What's the weather in NYC?")]})
print(result["messages"][-1].content)
```

## Agent with Memory

```python
from langgraph.checkpoint.memory import InMemorySaver

workflow = StateGraph(AgentState)
workflow.add_node("agent", call_model)
workflow.add_node("tools", ToolNode(tools))
workflow.set_entry_point("agent")
workflow.add_conditional_edges("agent", tools_condition)
workflow.add_edge("tools", "agent")

memory = InMemorySaver()
app = workflow.compile(checkpointer=memory)

config = {"configurable": {"thread_id": "user-123"}}

result1 = app.invoke(
    {"messages": [HumanMessage(content="My name is Veer")]},
    config=config
)

result2 = app.invoke(
    {"messages": [HumanMessage(content="What's my name?")]},
    config=config
)
# Agent remembers: "Your name is Veer"
```

## Streaming Agent Responses

```python
async for event in app.astream_events(
    {"messages": [HumanMessage(content="Write a poem about AI")]},
    version="v2"
):
    kind = event["event"]

    if kind == "on_chat_model_stream":
        content = event["data"]["chunk"].content
        if content:
            print(content, end="", flush=True)

    elif kind == "on_tool_start":
        print(f"\nTool called: {event['name']}")

    elif kind == "on_tool_end":
        print(f"Tool result: {event['data'].get('output', '')[:100]}...")
```

## Human-in-the-Loop

```python
app = workflow.compile(
    checkpointer=InMemorySaver(),
    interrupt_before=["tools"]  # Pause before tool execution
)

config = {"configurable": {"thread_id": "review-session"}}

result = app.invoke(
    {"messages": [HumanMessage(content="Search for latest AI news")]},
    config=config
)

state = app.get_state(config)
print(f"Pending tool calls: {state.values['messages'][-1].tool_calls}")

# User approves, continue execution
final = app.invoke(None, config=config)
```

## Complete Agent Example

```python
from typing import Annotated, Sequence, TypedDict
from langchain_core.messages import BaseMessage, HumanMessage
from langchain_core.tools import tool
from langchain_cohere import ChatCohere
from langgraph.graph import StateGraph, END
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode, tools_condition
from langgraph.checkpoint.memory import InMemorySaver

@tool
def web_search(query: str) -> str:
    """Search the web for information."""
    return f"Search results for '{query}': Latest AI breakthroughs..."

@tool
def multiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b

class State(TypedDict):
    messages: Annotated[Sequence[BaseMessage], add_messages]

llm = ChatCohere(model="command-a-03-2025")
tools = [web_search, multiply]
llm_with_tools = llm.bind_tools(tools)

def agent(state: State):
    return {"messages": [llm_with_tools.invoke(state["messages"])]}

graph = StateGraph(State)
graph.add_node("agent", agent)
graph.add_node("tools", ToolNode(tools))
graph.set_entry_point("agent")
graph.add_conditional_edges("agent", tools_condition)
graph.add_edge("tools", "agent")

app = graph.compile(checkpointer=InMemorySaver())

def chat(message: str, thread_id: str = "default"):
    config = {"configurable": {"thread_id": thread_id}}
    result = app.invoke({"messages": [HumanMessage(content=message)]}, config=config)
    return result["messages"][-1].content

print(chat("What is 15 times 23?"))
```

Overview

This skill is a practical reference for building Cohere-powered LangGraph agents, covering prebuilt ReAct agents, custom agent graphs, memory, streaming, and human-in-the-loop flows. It consolidates patterns for integrating Cohere chat, embeddings, reranking, structured outputs, and tool use into multi-tool and multi-step workflows. The content focuses on concrete examples and best practices for production-ready agents using Cohere APIs with LangGraph.

How this skill works

The skill shows how to wire a Cohere chat LLM into LangGraph state graphs, bind tools, and define conditional flows between model nodes and tool nodes. It demonstrates prebuilt ReAct agents for quick setups and custom StateGraph constructions for advanced control, including checkpoints for memory and event streams for real-time output. Example snippets cover tool registration, safe tool execution, thread-scoped memory, streaming events, and pausing execution for human approval.

When to use it

  • Build multi-step workflows that require tool calls, retrieval, or external APIs.
  • Need Cohere-specific features like citation support, streaming, or structured outputs.
  • Add thread-scoped memory to preserve user context across conversational turns.
  • Implement human-in-the-loop review or approval before executing potentially risky tools.
  • Prototype quickly using a prebuilt ReAct agent with Cohere optimizations.

Best practices

  • Bind tools to the LLM with explicit tool decorators and validate inputs/outputs for safety.
  • Use the prebuilt create_cohere_react_agent for token-efficient, Cohere-optimized reasoning chains.
  • Persist conversation state with a checkpointer (e.g., InMemorySaver or production store) scoped by thread_id.
  • Pause before tool execution when human review is required; resume by invoking the workflow again.
  • Stream events for large or long-running responses to provide immediate user feedback.

Example use cases

  • Customer support assistant that calls knowledge-base search and structured ticket-creation tools.
  • Data science helper that evaluates expressions, runs safe calculators, and summarizes results.
  • Research assistant that performs web searches, reranks results with embeddings, and composes citations.
  • Interactive tutoring bot that remembers a student profile across sessions and can request review before grading.
  • Automation orchestrator that chains multiple tools and human approvals for sensitive actions.

FAQ

When should I use the Cohere-specific ReAct agent versus a generic agent?

Use the Cohere-specific ReAct agent for complex, long reasoning chains and when you need Cohere features like streaming or structured outputs; use a generic agent for simple, provider-agnostic tool calling.

How do I keep user context between invocations?

Compile the graph with a checkpointer and pass a configurable thread_id; the checkpointer stores state per thread so subsequent invokes can access prior messages.