Files
magnus919_agent-skills/langchain/references/agent-patterns.md
T
Magnus Hedemark 7f2842b358 feat: langchain v1.1.0 — research-validated deepening
Major deepening of the langchain expert skill based on source audit against
official LangChain docs (docs.langchain.com, reference.langchain.com).

Changes:
- Added references/validation-audit.md documenting all research findings
- Deepened references/agent-patterns.md from 74 to 200+ lines:
  create_react_agent full parameter table, @tool decorator with
  args_schema/parse_docstring, streaming events, multi-agent supervisor
- Deepened references/lcel-reference.md from 79 to 180+ lines:
  RunnablePassthrough.assign(), RunnableParallel dict shorthand,
  RunnableLambda, RunnableConfig, .with_fallbacks(), .configurable_fields()
- Deepened references/rag-strategies.md with advanced retrieval patterns
- Deepened references/production-deployment.md with LangSmith Datasets/
  Evaluation Runs/Prompt Hub
- Added new references/callbacks.md (BaseCallbackHandler, event table,
  agent auditing patterns, async callbacks)
- Deepened references/faq-and-troubleshooting.md with Pydantic v1/v2,
  streaming+tools, checkpoint serialization guidance

All API surface claims verified against official documentation.
v1.0.3 -> v1.1.0
2026-07-09 14:33:42 -04:00

147 lines
4.9 KiB
Markdown

# LangChain Agent Patterns
## Agent Creation (v1.0+ — Recommended)
The recommended way to create agents in LangChain v1.0+. Generates a LangGraph state machine underneath — giving you streaming, checkpointing, and observability without writing graph code.
```python
from langchain.agents import create_agent
from langchain.tools import tool
@tool
def search_web(query: str) -> str:
'''Search the web for current information.'''
return f"Results for: {query}"
model = ChatOpenAI(model="gpt-4o")
agent = create_agent(model, tools=[search_web], prompt="You are a helpful assistant.")
result = agent.invoke({"messages": [("user", "Search for LangChain v1.0")]})
```
## create_react_agent (Deprecated — Legacy)
```python
from langgraph.prebuilt import create_react_agent
```
**Deprecated in v1.0** in favor of `create_agent` from `langchain.agents`. The full signature (18+ parameters) remains available for migration:
| Parameter | Type | Purpose |
|-----------|------|---------|
| `model` | str or LanguageModelLike | LLM to power the agent |
| `tools` | Sequence[BaseTool] | Tools the agent can call |
| `prompt` | str, SystemMessage, or Callable | System prompt added to messages |
| `response_format` | Pydantic / JSON Schema | Structured output schema |
| `pre_model_hook` | RunnableLike | Truncate/trim messages before LLM call |
| `post_model_hook` | RunnableLike | Guardrails/validation after LLM call |
| `checkpointer` | Checkpointer | Persist conversation state |
| `store` | BaseStore | Cross-thread persistent memory |
| `interrupt_before` | list[str] | Halt before specific nodes |
| `interrupt_after` | list[str] | Halt after specific nodes |
| `state_schema` | TypedDict | Custom graph state schema |
| `version` | 'v1' or 'v2' | Graph version (default: v2) |
## @tool Decorator — Full Reference
```python
from langchain.tools import tool
```
| Parameter | Default | Description |
|-----------|---------|-------------|
| `name_or_callable` | (first arg) | Tool name or decorated function |
| `return_direct` | `False` | Return tool output directly to user |
| `args_schema` | `None` | Pydantic model or JSON Schema for params |
| `infer_schema` | `True` | Auto-generate schema from type hints |
| `response_format` | `"content"` | `"content"` or `"content_and_artifact"` |
| `parse_docstring` | `False` | Parse Google-style docstrings into schema |
**Critical:** `parse_docstring=False` by default — parameter descriptions in docstrings are NOT included in the tool schema. Enable it:
```python
@tool(parse_docstring=True)
def search(query: str, limit: int = 10) -> str:
"""Search the database.
Args:
query: Search terms to look for
limit: Max results to return
"""
return f"{limit} results for '{query}'"
```
Type hints are **required** — they define the tool's input schema.
### args_schema with Pydantic
```python
from pydantic import BaseModel, Field
class WeatherInput(BaseModel):
location: str = Field(description="City name or coordinates")
units: str = Field(default="celsius", description="Temperature unit")
@tool(args_schema=WeatherInput)
def get_weather(location: str, units: str = "celsius") -> str:
"""Get current weather."""
return f"{location}: 22{units[0].upper()}"
```
### Reserved Parameter Names
| Name | Purpose |
|------|---------|
| `config` | RunnableConfig for callbacks and tags |
| `runtime` | ToolRuntime for state, context, store access |
## Streaming with Agents
```python
from langchain.agents import create_agent
agent = create_agent(model, tools, prompt="You are helpful.")
async for event in agent.astream_events(
{"messages": [("user", "Research LangChain RAG")]},
version="v2"
):
kind = event["event"]
if kind == "on_chat_model_stream":
print(event["data"]["chunk"].content, end="")
elif kind == "on_tool_start":
print(f"\n[Calling tool: {event['name']}]")
```
Streaming events include: `on_chat_model_start`, `on_chat_model_stream`, `on_tool_start`, `on_tool_end`, `on_retriever_start`, `on_retriever_end`.
## Multi-Agent with Supervisor
For multiple coordinated agents, use LangGraph's StateGraph directly:
```python
from langgraph.graph import StateGraph, END
from typing import TypedDict, Literal
class AgentState(TypedDict):
messages: list
next: str
graph = StateGraph(AgentState)
graph.add_node("supervisor", supervisor_agent)
graph.add_node("researcher", research_agent)
graph.add_node("writer", writer_agent)
graph.add_conditional_edges("supervisor", lambda s: s["next"])
graph.add_edge("researcher", "supervisor")
graph.add_edge("writer", END)
```
## Key v1.0 Migration
| Old pattern | New pattern (v1.0+) |
|-------------|---------------------|
| `AgentExecutor` | `create_agent` (uses LangGraph) |
| `initialize_agent` | `create_agent` |
| `LLMChain` | LCEL: `prompt | model | parser` |
| `ConversationBufferMemory` | LangGraph checkpointer |
| `agent.run()` | `agent.invoke()` |