# LangChain Integration Guide

This guide shows how to use cascadeflow with LangChain for intelligent AI model cascading with 40-85% cost savings while maintaining full LangChain compatibility.

## Table of Contents

1. [Overview](#overview)
2. [Installation](#installation)
3. [Quick Start](#quick-start)
4. [Configuration](#configuration)
5. [Key Features](#key-features)
6. [Use Cases](#use-cases)
7. [Best Practices](#best-practices)
8. [Troubleshooting](#troubleshooting)
9. [Harness Integration (Python)](#harness-integration-python)

---

## Overview

The **@cascadeflow/langchain** package brings cascadeflow's intelligent model cascading to LangChain applications as a drop-in replacement for standard LangChain chat models.

### What is Model Cascading?

Instead of always using expensive models:

```
Traditional: Every query → GPT-4o ($0.0025)
```

cascadeflow tries cheap models first:

```
cascadeflow:
  1. Try GPT-4o-mini ($0.00015) ← 70-80% stop here! ✅
  2. Validate quality automatically
  3. If needed → GPT-4o ($0.0025)

Result: 50-85% cost savings
```

### How It Works with LangChain

cascadeflow wraps any LangChain chat model and provides intelligent routing:

**Architecture:**

```
┌─────────────────────────────────────────┐
│         Your LangChain Application       │
│                                          │
│  ┌────────────────────────────────────┐ │
│  │      withCascade (Proxy)        │ │
│  ├────────────────────────────────────┤ │
│  │  1. Route to Drafter (GPT-4o-mini) │ │
│  │  2. Quality Check (90% pass!)      │ │
│  │  3. Escalate to Verifier if needed │ │
│  └────────────────────────────────────┘ │
│                                          │
│  Supports: LCEL, Streaming, Tools, Batch │
└─────────────────────────────────────────┘
```

**Key Benefits:**
- 🎯 **Drop-in Replacement**: Works with all LangChain features
- 💰 **Cost Savings**: 40-85% reduction in API costs
- ⚡ **Speed**: Faster responses (drafter is quicker)
- 🔧 **Zero Config**: Works out of the box with sensible defaults
- 📊 **LangSmith Integration**: Automatic cost tracking metadata
- 🧭 **Domain-Aware Routing**: Per-domain overrides for threshold and verifier policy
- 🔁 **Agent Loops**: Built-in `CascadeAgent` for closed tool/model loops with max-step safety

---

## Installation

```bash
npm install @cascadeflow/langchain @langchain/core @langchain/openai
```

Or with yarn:

```bash
yarn add @cascadeflow/langchain @langchain/core @langchain/openai
```

---

## Quick Start

### Basic Usage

```typescript
import { ChatOpenAI } from '@langchain/openai';
import { withCascade } from '@cascadeflow/langchain';

// Create your models
const drafter = new ChatOpenAI({
  model: 'gpt-4o-mini',
  temperature: 0.7
});

const verifier = new ChatOpenAI({
  model: 'gpt-4o',
  temperature: 0.7
});

// Wrap them with cascade
const cascade = withCascade({
  drafter,
  verifier,
  qualityThreshold: 0.7,
});

// Use it like any LangChain chat model
const response = await cascade.invoke('Explain quantum computing');
console.log(response.content);
```

### With LCEL (LangChain Expression Language)

```typescript
import { PromptTemplate } from '@langchain/core/prompts';
import { StringOutputParser } from '@langchain/core/output_parsers';

const prompt = PromptTemplate.fromTemplate(
  'You are a helpful assistant. Answer: {question}'
);

// Chain with cascade using pipe
const chain = prompt
  .pipe(cascade)
  .pipe(new StringOutputParser());

const result = await chain.invoke({
  question: 'What is machine learning?'
});
```

---

## Configuration

### withCascade Options

```typescript
interface CascadeConfig {
  // Required: The fast, cheap model
  drafter: BaseChatModel;

  // Required: The high-quality model (fallback)
  verifier: BaseChatModel;

  // Quality threshold (0-1). Default: 0.7
  qualityThreshold?: number;

  // Enable automatic cost tracking (default true)
  enableCostTracking?: boolean;

  // Cost tracking provider:
  // - 'cascadeflow' (default): compute costs locally via CascadeFlow's pricebook
  // - 'langsmith': LangSmith computes costs server-side (local costs will be $0)
  costTrackingProvider?: 'langsmith' | 'cascadeflow'; // default: 'cascadeflow'

  // Optional custom quality validator (0-1)
  qualityValidator?: (response: any) => Promise<number> | number;

  // Enable complexity pre-routing (default true)
  enablePreRouter?: boolean;

  // Optional: provide a custom PreRouter instance
  preRouter?: PreRouter;

  // Complexity levels that should use cascade first
  cascadeComplexities?: QueryComplexity[];

  // Optional per-domain overrides (domain key is case-insensitive)
  domainPolicies?: Record<string, {
    qualityThreshold?: number;
    forceVerifier?: boolean;
    directToVerifier?: boolean;
    metadata?: Record<string, any>;
  }>;
}
```

### Quality Threshold Guide

| Threshold | Drafter Usage | Use Case |
|-----------|---------------|----------|
| 0.9 | ~90% | Simple Q&A, documentation |
| 0.8 | ~80% | General purpose (default) |
| 0.7 | ~70% | More critical tasks |
| 0.6 | ~60% | High-stakes decisions |

### Model Combinations

**OpenAI:**
```typescript
const drafter = new ChatOpenAI({ model: 'gpt-4o-mini' });
const verifier = new ChatOpenAI({ model: 'gpt-4o' });
```

**Anthropic:**
```typescript
import { ChatAnthropic } from '@langchain/anthropic';

const drafter = new ChatAnthropic({ modelName: 'claude-haiku-4-5-20251001' });
const verifier = new ChatAnthropic({ modelName: 'claude-opus-4-6' });
```

**Mix and Match:**
```typescript
// Cheap drafter (Haiku), powerful verifier (GPT-4o)
const drafter = new ChatAnthropic({ modelName: 'claude-haiku-4-5-20251001' });
const verifier = new ChatOpenAI({ model: 'gpt-4o' });
```

---

## Key Features

### 1. Streaming Support

Streaming support with automatic pre-routing:

```typescript
// Stream from cascade
const stream = await cascade.stream('Write a story about a robot');

for await (const chunk of stream) {
  process.stdout.write(chunk.content);
}
```

**How it works:**
- Pre-routing: Cascade may choose a single model (direct-to-verifier) before streaming starts.
- Text-only: Cascade streams the drafter optimistically, then escalates to the verifier only if needed.
- Tool-safe: If tools are bound via `bindTools(...)`, Cascade buffers the drafter stream and only emits chunks after the final model decision, so tool call deltas are never "changed mid-flight".
- Clean output by default: Cascade does not inject "switch" messages into the stream unless explicitly enabled.

To enable a debug "switch" message (TypeScript only), pass:
```typescript
const debugCascade = cascade.bind({ metadata: { cascadeflow_emit_switch_message: true } });
await debugCascade.stream("...");
```

### 2. Tool Calling & Function Calling

Bind tools to cascade - they propagate to both models:

```typescript
const tools = [
  {
    type: 'function',
    function: {
      name: 'calculator',
      description: 'Performs arithmetic operations',
      parameters: {
        type: 'object',
        properties: {
          operation: {
            type: 'string',
            enum: ['add', 'subtract', 'multiply', 'divide']
          },
          a: { type: 'number' },
          b: { type: 'number' },
        },
        required: ['operation', 'a', 'b'],
      },
    },
  },
];

// Bind tools to cascade
const boundCascade = cascade.bindTools(tools);

const result = await boundCascade.invoke(
  'What is 15 plus 27?'
);

// Result includes tool calls
console.log(result.tool_calls ?? result.additional_kwargs?.tool_calls);
```

**Safety policy (default):**
- Low/medium-risk tool calls are accepted without running the verifier (even if `content` is empty).
- High/critical-risk tool calls force a verifier run before returning a tool call.

Tool risk is classified from tool `name` and `description` (examples: `delete_user`, `send_email`, `payment`, `deploy_production`).

### 3. Domain Policies

Apply routing policy by domain without changing chain logic:

```typescript
const cascade = withCascade({
  drafter,
  verifier,
  qualityThreshold: 0.7,
  domainPolicies: {
    finance: { qualityThreshold: 0.5 },
    medical: { forceVerifier: true },
    legal: { directToVerifier: true },
  },
});

const legalCascade = cascade.bind({
  metadata: { cascadeflow_domain: 'legal' },
});

const result = await legalCascade.invoke('Review this contract clause');
```

Policy semantics:
- `qualityThreshold`: overrides global threshold for that domain
- `forceVerifier`: drafter still runs, but verifier is always called
- `directToVerifier`: skip drafter and route straight to verifier

### 4. Agent Loop with `CascadeAgent`

`CascadeAgent` runs model/tool/model loops with explicit stop conditions.

TypeScript:

```typescript
import { CascadeAgent, withCascade } from '@cascadeflow/langchain';

const cascade = withCascade({ drafter, verifier }).bindTools(tools);

const agent = new CascadeAgent({
  model: cascade,
  maxSteps: 6,
  toolHandlers: {
    // Use a strict parser helper (see examples/nodejs/safe-math.ts).
    calculator: async ({ expression }) => safeCalculateExpression(expression).toString(),
  },
});

const run = await agent.run(
  [{ role: 'user', content: 'What is (25*4)+10?' }],
  { systemPrompt: 'You are a reliable calculator.' }
);
```

Python:

```python
from cascadeflow.integrations.langchain import CascadeAgent, CascadeFlow

cascade = CascadeFlow(drafter=drafter, verifier=verifier)
agent = CascadeAgent(
    model=cascade.bind_tools(tools),
    max_steps=6,
    # Use a strict parser helper (see examples/agentic_multi_agent.py).
    tool_handlers={"calculator": lambda args: str(safe_calculate(args["expression"]))},
)

result = await agent.arun(
    [{"role": "user", "content": "What is (25*4)+10?"}],
    system_prompt="You are a reliable calculator.",
)
```

Input supports strings, LangChain message objects, and role/content message lists for multi-turn conversations.

### 5. Multi-Agent + LangGraph (Optional)

If you already use LangGraph for multi-agent systems, CascadeFlow can be used as the shared chat model inside nodes/sub-agents.

- TypeScript example: `packages/langchain-cascadeflow/examples/langgraph-multi-agent.ts`
- Python example: `examples/langchain_langgraph_multi_agent.py`

### 6. Structured Output

Extract structured data with schemas:

```typescript
const userSchema = {
  type: 'object',
  properties: {
    name: { type: 'string' },
    age: { type: 'number' },
    email: { type: 'string' },
  },
  required: ['name', 'age'],
};

const structuredCascade = cascade.withStructuredOutput(userSchema);

const result = await structuredCascade.invoke(
  'Extract info: John Smith is 28 years old. Email: john@example.com'
);

// { name: 'John Smith', age: 28, email: 'john@example.com' }
```

### 7. Batch Processing

Process multiple inputs efficiently:

```typescript
const questions = [
  'What is 2+2?',
  'What is the speed of light?',
  'Who wrote Romeo and Juliet?',
];

const results = await cascade.batch(questions);

results.forEach((result, i) => {
  console.log(`Q: ${questions[i]}`);
  console.log(`A: ${result.content}\n`);
});
```

### 8. LCEL Composition Patterns

See runnable examples:
- TypeScript: `packages/langchain-cascadeflow/examples/lcel-pipeline.ts`
- Python: `examples/langchain_lcel_pipeline.py`

**Sequential Chains:**
```typescript
import { RunnableSequence } from '@langchain/core/runnables';

const chain = RunnableSequence.from([
  prompt,
  cascade,
  new StringOutputParser(),
]);
```

**Parallel Branches:**
```typescript
import { RunnablePassthrough } from '@langchain/core/runnables';

const chain = RunnablePassthrough.assign({
  answer: cascade.pipe(new StringOutputParser()),
  context: () => 'Generated by cascadeflow',
});

const result = await chain.invoke('What is AI?');
// { answer: '...', context: 'Generated by cascadeflow' }
```

**Complex Patterns:**
```typescript
// Multi-step reasoning
const analysisChain = RunnableSequence.from([
  // Step 1: Analyze
  RunnablePassthrough.assign({
    analysis: cascade.pipe(new StringOutputParser()),
  }),
  // Step 2: Summarize
  (input) => ({
    question: input.question,
    analysis: input.analysis,
    prompt: `Summarize this analysis: ${input.analysis}`,
  }),
  // Step 3: Summary
  RunnablePassthrough.assign({
    summary: cascade.pipe(new StringOutputParser()),
  }),
]);
```

### 9. LangSmith Integration

CascadeFlow adds LangSmith-friendly `tags` and `metadata` to nested drafter/verifier runs so traces are searchable by:
- `cascadeflow:drafter`, `cascadeflow:verifier`
- `cascadeflow:direct`, `cascadeflow:escalated`
- `cascadeflow:toolrisk=HIGH|CRITICAL|...` (when tool calls occur)

Automatic cost tracking metadata:

```typescript
// Metadata is automatically injected into responses
const result = await cascade.invoke('test');

// Access via response_metadata
console.log(result.response_metadata?.cascade);
/*
{
  modelUsed: 'drafter',
  accepted: true,
  drafterQuality: 0.75,
  drafterTokens: { input: 123, output: 45 },
  verifierTokens: undefined,
  drafterCost: 0,
  verifierCost: 0,
  totalCost: 0,
  savingsPercentage: 0,
  cascade_decision: 'accepted'
}
*/
```

View in LangSmith traces:
1. Open LangSmith dashboard
2. View trace for your request
3. Check metadata for cost breakdown
4. Track savings over time

---

## Use Cases

### 1. Customer Support Chatbot

```typescript
import { ChatOpenAI } from '@langchain/openai';
import { withCascade } from '@cascadeflow/langchain';
import { PromptTemplate } from '@langchain/core/prompts';

const supportPrompt = PromptTemplate.fromTemplate(`
You are a helpful customer support agent.
Previous context: {context}
User question: {question}

Provide a clear, helpful answer.
`);

const cascade = withCascade({
  drafter: new ChatOpenAI({ model: 'gpt-4o-mini' }),
  verifier: new ChatOpenAI({ model: 'gpt-4o' }),
  qualityThreshold: 0.85, // Most queries use cheap model
});

const chain = supportPrompt.pipe(cascade);

// Simple questions → drafter (cheap)
await chain.invoke({
  context: '',
  question: 'What are your business hours?',
});

// Complex questions → verifier (expensive)
await chain.invoke({
  context: 'User has account issues',
  question: 'How do I recover my account with 2FA enabled?',
});
```

**Savings:** 70-80% cost reduction on support queries

### 2. Document Q&A with RAG

```typescript
import { ChatOpenAI } from '@langchain/openai';
import { withCascade } from '@cascadeflow/langchain';
import { PromptTemplate } from '@langchain/core/prompts';
import { StringOutputParser } from '@langchain/core/output_parsers';

const ragPrompt = PromptTemplate.fromTemplate(`
Context: {context}

Question: {question}

Answer based on the context above.
`);

const cascade = withCascade({
  drafter: new ChatOpenAI({ model: 'gpt-4o-mini' }),
  verifier: new ChatOpenAI({ model: 'gpt-4o' }),
  qualityThreshold: 0.8,
});

const chain = ragPrompt
  .pipe(cascade)
  .pipe(new StringOutputParser());

const answer = await chain.invoke({
  context: retrievedDocs,
  question: userQuestion,
});
```

**Savings:** 60-75% cost reduction on RAG applications

### 3. Data Extraction Pipeline

```typescript
const extractionSchema = {
  type: 'object',
  properties: {
    entities: {
      type: 'array',
      items: {
        type: 'object',
        properties: {
          name: { type: 'string' },
          type: { type: 'string' },
          confidence: { type: 'number' },
        },
      },
    },
  },
};

const cascade = withCascade({
  drafter: new ChatOpenAI({ model: 'gpt-4o-mini' }),
  verifier: new ChatOpenAI({ model: 'gpt-4o' }),
});

const extractor = cascade.withStructuredOutput(extractionSchema);

// Batch process documents
const documents = [...]; // Your documents
const results = await extractor.batch(
  documents.map(doc => `Extract entities from: ${doc}`)
);
```

**Savings:** 50-70% cost reduction on extraction tasks

### 4. Code Review Assistant

```typescript
const codeReviewPrompt = PromptTemplate.fromTemplate(`
Review this code for best practices, bugs, and improvements:

{code}

Provide:
1. Issues found (if any)
2. Suggested improvements
3. Overall assessment
`);

const cascade = withCascade({
  drafter: new ChatOpenAI({ model: 'gpt-4o-mini' }),
  verifier: new ChatOpenAI({ model: 'gpt-4o' }),
  qualityThreshold: 0.75, // More critical task
});

const chain = codeReviewPrompt.pipe(cascade);

const review = await chain.invoke({ code: userCode });
```

**Savings:** 60-70% cost reduction on code reviews

---

## Best Practices

### 1. Choose the Right Quality Threshold

```typescript
// High-volume, low-stakes
const chatbot = withCascade({
  drafter, verifier,
  qualityThreshold: 0.9, // 90% use drafter
});

// Critical business logic
const criticalAnalysis = withCascade({
  drafter, verifier,
  qualityThreshold: 0.6, // 60% use drafter
});
```

### 2. Monitor with LangSmith

```typescript
import { LangChainTracer } from 'langchain/callbacks';

const tracer = new LangChainTracer({
  projectName: 'my-cascade-project',
});

const result = await cascade.invoke('test', {
  callbacks: [tracer],
});

// View traces in LangSmith dashboard
// Track: route decisions, costs, quality scores
```

### 3. Custom Quality Checks

```typescript
const cascade = withCascade({
  drafter,
  verifier,
  qualityValidator: async (chatResult) => {
    // `chatResult` is a LangChain ChatResult-like object.
    const content =
      chatResult?.generations?.[0]?.text ??
      chatResult?.generations?.[0]?.message?.content ??
      '';

    // Check length
    if (content.length < 50) return 0.5;

    // Check for specific keywords
    if (content.includes('I don\'t know')) return 0.3;

    // Check for citations
    if (content.match(/\[\d+\]/)) return 0.9;

    return 0.8; // Default score
  },
});
```

### 4. Optimize Model Selection

**For Simple Tasks:**
```typescript
// Use smallest models
const drafter = new ChatOpenAI({ model: 'gpt-4o-mini' });
const verifier = new ChatOpenAI({ model: 'gpt-4o-mini' }); // Same model
// Set high threshold
qualityThreshold: 0.95
```

**For Complex Tasks:**
```typescript
// Use model gap
const drafter = new ChatOpenAI({ model: 'gpt-4o-mini' });
const verifier = new ChatOpenAI({ model: 'gpt-4o' });
// Set moderate threshold
qualityThreshold: 0.7
```

### 5. Streaming Best Practices

```typescript
// Text-only: drafter streams optimistically, verifier streams only if needed
const stream = await cascade.stream(input);

for await (const chunk of stream) {
  // Handle chunks
  process.stdout.write(chunk.content);
}
```

---

## Troubleshooting

### Issue: Too Many Verifier Calls

**Symptom:** Higher costs than expected

**Solution 1:** Increase quality threshold
```typescript
const cascade = withCascade({
  drafter, verifier,
  qualityThreshold: 0.85, // Increased from 0.8
});
```

**Solution 2:** Improve drafter model
```typescript
// Use better drafter
const drafter = new ChatOpenAI({
  model: 'gpt-4o-mini',
  temperature: 0.3, // More deterministic
});
```

**Solution 3:** Add custom quality check
```typescript
qualityValidator: async () => 0.9
```

### Issue: Tools Not Working

**Symptom:** Tool calls not appearing

**Solution:** Ensure models support tools
```typescript
// ✅ Good - models support tools
const drafter = new ChatOpenAI({ model: 'gpt-4o-mini' });
const verifier = new ChatOpenAI({ model: 'gpt-4o' });

// ❌ Bad - model doesn't support tools
const drafter = new ChatOpenAI({ model: 'gpt-3.5-turbo' });
```

### Issue: Streaming Not Working

**Symptom:** No chunks received

**Solution:** Check model streaming support
```typescript
// Ensure both models support streaming
const drafter = new ChatOpenAI({
  model: 'gpt-4o-mini',
  streaming: true, // Enable streaming
});
```

### Issue: Type Errors with LCEL

**Symptom:** TypeScript errors in chains

**Solution:** Use explicit types
```typescript
import type { Runnable } from '@langchain/core/runnables';

const cascade: Runnable = withCascade({
  drafter, verifier,
});

const chain = cascade.pipe(new StringOutputParser());
```

### Issue: Metadata Not Appearing

**Symptom:** No cascade metadata in responses

**Solution:** Check response_metadata
```typescript
const result = await cascade.invoke('test');

// Access metadata correctly
console.log(result.response_metadata?.cascade);

// Not result.metadata (wrong)
```

---

## Harness Integration (Python)

The cascadeflow harness adds multi-dimensional budget enforcement, energy tracking,
tool call gating, and trace recording to LangChain applications via a callback handler.

### Design Principles

- **Callback-based** — Uses LangChain's native callback system to intercept every
  LLM and tool call. Works with any chain, agent, or LangGraph graph.
- **Opt-in** — Install `cascadeflow[langchain]` and pass the callback explicitly.
  Never enabled by default.
- **Fail-open** — Integration errors are logged but never break chain execution
  (configurable).
- **No model switching** — LangChain dispatches the LLM call before `on_llm_start`
  returns, so the callback cannot redirect to a different model. `switch_model`
  decisions are recorded with `applied=False` for observability.

### Install

```bash
pip install "cascadeflow[langchain]"
```

Requires Python 3.10+.

### Quick Start

```python
from langchain_openai import ChatOpenAI
from cascadeflow import init, run
from cascadeflow.integrations.langchain import get_harness_callback

# 1. Initialize harness globally
init(mode="observe", budget=1.0)

model = ChatOpenAI(model="gpt-4o-mini")

# 2. Use the harness-aware callback in a run scope
with run(budget=0.5) as session:
    with get_harness_callback() as cb:
        response = model.invoke(
            "Explain why model routing helps agent budgets.",
            config={"callbacks": [cb]},
        )

    print(response.content)
    print(f"Cost: ${session.cost:.6f}")
    print(f"Steps: {session.step_count}")
    print(f"Tool calls: {session.tool_calls}")
    for event in session.trace():
        print(event)
```

### What This Integration Adds

- Budget gating in enforce mode (`on_llm_start` raises `HarnessStopError`)
- Tool call gating in enforce mode (`on_tool_start` raises `HarnessStopError`)
- Run metrics on `cascadeflow.run()` scope:
  - `cost`, `budget_remaining`, `step_count`, `tool_calls`, `latency_used_ms`, `energy_used`
- Full decision trace through `session.trace()`
- LangGraph state extraction — automatically syncs `step_count`, `tool_calls`,
  `budget_remaining`, `latency_used_ms`, `energy_used` from graph state payloads

### Enforce-Mode Limitations

| Decision | Enforced? | Notes |
|----------|-----------|-------|
| `stop` (budget/latency/energy) | Yes | Raises `HarnessStopError` from `on_llm_start` |
| `deny_tool` (tool cap) | Yes | Raises `HarnessStopError` from `on_tool_start` |
| `switch_model` | Observe-only | Recorded with `applied=False` — LangChain cannot redirect mid-call |
| `deny_tool` (LLM-level) | Observe-only | Cannot strip tools from already-dispatched request |

### Configuration

```python
from cascadeflow.integrations.langchain import (
    HarnessAwareCascadeFlowCallbackHandler,
    get_harness_callback,
)

# Context manager (recommended)
with get_harness_callback(fail_open=True) as cb:
    result = model.invoke("...", config={"callbacks": [cb]})

# Direct instantiation
cb = HarnessAwareCascadeFlowCallbackHandler(fail_open=True)
result = model.invoke("...", config={"callbacks": [cb]})
```

### With LangGraph

The callback automatically extracts harness-relevant state from LangGraph payloads
(via `langgraph_state`, `graph_state`, or `state` keys in metadata/configurable).

```python
from langgraph.graph import StateGraph
from cascadeflow import init, run
from cascadeflow.integrations.langchain import get_harness_callback

init(mode="observe", budget=1.0)

# Build your graph as normal
graph = builder.compile()

with run(budget=0.5) as session:
    with get_harness_callback() as cb:
        result = graph.invoke(
            {"messages": [("user", "What is model routing?")]},
            config={"callbacks": [cb]},
        )
    print(session.summary())
```

### Troubleshooting

| Symptom | Solution |
|---------|----------|
| `ImportError: cascadeflow.integrations.langchain` | `pip install "cascadeflow[langchain]"` |
| Callback not tracking calls | Ensure `cb` is passed in `config={"callbacks": [cb]}` |
| Budget not enforced | Check `init(mode="enforce", ...)` — observe mode never blocks |
| Zero cost reported | Model name may not match pricing table; check `response.response_metadata` |

---

## Next Steps

1. **Examples**: Check the `examples/` directory for more patterns
2. **API Reference**: See the [package README](../../packages/langchain-cascadeflow/README.md)
3. **LangSmith**: Set up tracing for cost monitoring
4. **Production**: Read the [production guide](./production.md)

---

## Additional Resources

- [LangChain Documentation](https://js.langchain.com/)
- [cascadeflow Core Guide](../README.md)
- [Cost Optimization Guide](./cost_tracking.md)
- [Performance Guide](./performance.md)

---

**Questions or Issues?**
- GitHub: [cascadeflow Issues](https://github.com/lemony-ai/cascadeflow/issues)
- Email: hello@lemony.ai
