langchain-nimble
Production-grade LangChain integration for Nimble's Web Search & Content Extraction API
langchain-nimble provides powerful web search and content extraction capabilities for LangChain applications. Built on the official Nimble Python SDK, it offers both retrievers and tools for seamless integration with LangChain agents and chains.
Features
- ✨ Dual Interface: Retrievers for chains, Tools for agents
- 🔍 Search Depth Levels: lite (metadata), fast (Enterprise), deep (full content)
- 🤖 LLM Answers: Optional AI-generated answer summaries
- 🎯 Focus Modes: Specialized search (general, news, location, shopping, geo, social)
- 📋 Extract Templates: Structured site scraping (
nimble_extract_template_*) - 🤖 Agent API V2: Resumable Web Search Agent research (
start/status/result) - ⏰ Time Range Filtering: Quick recency filters (hour, day, week, month, year)
- 📅 Date Filtering: Search by specific date ranges
- 🌐 Domain Control: Include/exclude specific domains
- ⚡ Full Async Support: Both sync and async implementations
- 🔄 Smart Retry Logic: Built-in retry via Nimble SDK
- 📊 Markdown Output: Clean markdown content from any page
Installation
pip install -U langchain-nimble
Quick Start
1. Get Your API Key
Sign up at Nimbleway to get your API key.
2. Set Environment Variable
export NIMBLE_API_KEY="your-api-key-here"
Or pass it directly: NimbleSearchRetriever(api_key="your-key")
3. Basic Usage
from langchain_nimble import NimbleSearchRetriever
# Create a retriever
retriever = NimbleSearchRetriever(max_results=5)
# Search (sync or async with ainvoke)
documents = retriever.invoke("latest developments in AI")
for doc in documents:
print(f"{doc.metadata['title']}\n{doc.metadata['url']}\n")
Retrievers
Retrievers return LangChain Document objects, ideal for RAG pipelines and chains.
NimbleSearchRetriever
Basic Search
from langchain_nimble import NimbleSearchRetriever
# Lite search - returns metadata only (default)
retriever = NimbleSearchRetriever(
max_results=5,
search_depth="lite"
)
docs = retriever.invoke("Python best practices 2024")
Deep Search
Fetch full page content from each result:
retriever = NimbleSearchRetriever(
max_results=3,
search_depth="deep" # Full page content extraction
)
docs = retriever.invoke("comprehensive guide to FastAPI")
Advanced Filtering
# Domain filtering
retriever = NimbleSearchRetriever(
max_results=5,
include_domains=["python.org", "docs.python.org"],
exclude_domains=["pinterest.com"]
)
# Date filtering
retriever = NimbleSearchRetriever(
max_results=10,
start_date="2024-01-01",
end_date="2024-12-31",
focus="news"
)
# Time range filtering
recent_retriever = NimbleSearchRetriever(
time_range="week" # hour, day, week, month, year
)
# Focus-based search
news_retriever = NimbleSearchRetriever(focus="news")
location_retriever = NimbleSearchRetriever(focus="location")
shopping_retriever = NimbleSearchRetriever(focus="shopping") # AI-powered WSA
LLM Answer Generation
Get AI-generated answers:
retriever = NimbleSearchRetriever(
max_results=5,
include_answer=True
)
docs = retriever.invoke("What is the capital of France?")
# First doc contains the LLM answer if available
if docs and docs[0].metadata.get("entity_type") == "answer":
print(f"Answer: {docs[0].page_content}")
NimbleExtractRetriever
Extract content from specific URLs:
from langchain_nimble import NimbleExtractRetriever
retriever = NimbleExtractRetriever()
docs = retriever.invoke("https://www.python.org/about/")
# With render wait for dynamic content
retriever = NimbleExtractRetriever(
driver="vx8", # Optional: vx6, vx8, vx8-pro, vx10, vx10-pro, vx12, vx12-pro
wait=3000, # Wait for dynamic content (ms) - uses browser_actions
)
Tools for Agents
Tools provide structured input schemas for agent integration.
NimbleSearchTool
from langchain_nimble import NimbleSearchTool
from langchain.agents import create_agent
# Create agent with search tool
search_tool = NimbleSearchTool()
agent = create_agent(
model="claude-haiku-4-5",
tools=[search_tool]
)
# Agent searches the web
response = agent.invoke({
"messages": [{"role": "user", "content": "What are the latest developments in quantum computing?"}]
})
NimbleExtractTool
from langchain_nimble import NimbleExtractTool
extract_tool = NimbleExtractTool()
# Extract a URL - returns markdown string
result = extract_tool.invoke({
"url": "https://www.langchain.com/"
})
Extract Templates (structured site scraping)
Use when you need a named template (e.g. product pages) with structured params — distinct from URL markdown extract and from Agent API V2 research.
from langchain_nimble import NimbleToolkit
toolkit = NimbleToolkit(include_extract_templates=True)
tools = toolkit.get_tools()
# nimble_extract_template_list → get → run
Or import tools directly: NimbleExtractTemplateListTool, NimbleExtractTemplateGetTool, NimbleExtractTemplateRunTool.
Deprecated:
NimbleAgentListTool/Get/Run(nimble_agent_*) are aliases that now wrap Extract Templates. Prefer thenimble_extract_template_*names. They do not call Agent API V2.
Agent API V2 (Web Search Agents / research)
Resumable research agents under /v2/agents/*. Distinct from Extract Templates.
LangChain tool sessions are typically stateless, so prefer Mode 1
(agent_name create-or-reuse) on nimble_web_search_agent_run_start. Use
Mode 2 (agent_id / wsa_…) when your app persists the id. Omit both for
Mode 3 anonymous one-shot (response still includes web_search_agent_id).
Start / status / result are separate tools — do not hide multi-minute polling in one call. Runs often take 3–15 minutes.
from langchain_nimble import NimbleToolkit
toolkit = NimbleToolkit(include_web_search_agents=True)
tools = toolkit.get_tools()
# nimble_web_search_agents_list, nimble_web_search_agent_templates_list,
# nimble_web_search_agent_create, nimble_web_search_agent_run_start,
# nimble_web_search_agent_run_status, nimble_web_search_agent_run_result
Modes (runnable sketches)
Mode 1 — create-or-reuse by name (default for stateless hosts):
from langchain_nimble import NimbleAgentRunStartTool, NimbleAgentRunStatusTool, NimbleAgentRunResultTool
start = NimbleAgentRunStartTool()
started = start.invoke({
"agent_name": "integrations_research_bot",
"use_case": "research",
"effort": "medium",
"skill": "Focus on official docs and changelogs",
"input": "Summarize recent Agent API v2 changes for integrators.",
})
# started["id"] -> task_run_… ; started["web_search_agent_id"] -> wsa_…
# Reuse the same agent_name later; a failed first run does not brick the name.
Mode 2 — persist wsa_…:
from langchain_nimble import NimbleAgentCreateTool, NimbleAgentRunStartTool
create = NimbleAgentCreateTool()
agent = create.invoke({
"agent_name": "enrich_bot",
"use_case": "enrichment",
"skill": "Company firmographics",
"output_schema": {"type": "object", "properties": {"domain": {"type": "string"}}},
})
start = NimbleAgentRunStartTool()
started = start.invoke({
"agent_id": agent["id"],
"input": "Enrich this company row",
"input_data": [{"domain": "example.com"}],
"effort": "medium",
})
Mode 3 — anonymous one-shot: omit agent_id and agent_name; still read
web_search_agent_id from the start response if you want to graduate to Mode 2.
Effort tiers
| Tier | Guidance |
|---|---|
low |
~15–17s; may skip live research (0 sources / low confidence) |
medium |
~90–160s observed — good default for real research |
high / x-high / max |
Longer; design UX for 3–15 minutes wall time |
use_case (locked, not a silent per-run override)
| Value | Output | When |
|---|---|---|
research |
output.type: "text" + citations |
Free-form cited answer |
enrichment |
output.type: "json" |
Fill input_data against a schema |
dataset_building |
output.type: "json" |
Structured table from scratch (API requires effort high+) |
Set once when the agent is created (Mode 1 first call, Mode 3, or
nimble_web_search_agent_create). Against an existing agent: omit or pass the
same value — a different value returns 422.
Overrides vs persist
On an existing agent, run-level sources / output_schema / skill are
one-time (they do not mutate the stored agent). On Mode 1 first create,
those fields are stored. input_data is always run-only (enrichment
payload ≠ schema). use_case is never a silent override.
sources fields
sources = {
"allow": [{"title": "Official filings", "domains": ["sec.gov"], "order": 0}],
"block": [{"title": "Junk", "domains": ["example.com"], "order": 0}],
"avoid": "free-text domains or source types to avoid",
"prioritize": "free-text domains or source types to prefer",
}
Events (intentional gap)
API supports enable_events: true + GET …/runs/{run_id}/events (SSE). This
package does not expose a separate events tool yet — use start/status/result.
Attribution: every request sends X-Client-Source: langchain-nimble.
Multi-Tool Agent
from langchain_nimble import NimbleSearchTool, NimbleExtractTool
from langchain.agents import create_agent
search_tool = NimbleSearchTool()
extract_tool = NimbleExtractTool()
agent = create_agent(
model="claude-haiku-4-5",
tools=[search_tool, extract_tool]
)
# Agent can search, then extract specific URLs
response = agent.invoke({
"messages": [{"role": "user", "content": "Find recent LangChain articles and summarize the top one"}]
})
Parameter Reference
Search Parameters (NimbleSearchRetriever & NimbleSearchTool)
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key |
str | None |
None |
API key (or set NIMBLE_API_KEY) |
max_results |
int |
3 / 10* |
Number of results (1-100). Alias: num_results |
focus |
str |
"general" |
Search focus mode |
search_depth |
str |
"lite" |
Search depth: lite, fast (Enterprise), deep |
include_answer |
bool |
False |
LLM answer summary |
time_range |
str |
None |
Recency filter - hour, day, week, month, year |
include_domains |
list[str] |
None |
Domain whitelist |
exclude_domains |
list[str] |
None |
Domain blacklist |
start_date |
str |
None |
Filter after date (YYYY-MM-DD or YYYY) |
end_date |
str |
None |
Filter before date (YYYY-MM-DD or YYYY) |
locale |
str |
"en" |
Language/locale (e.g., fr, es) |
country |
str |
"US" |
Country code (e.g., UK, FR) |
* Defaults differ: Retriever uses max_results=3, search_depth="lite"; Tool uses max_results=10, search_depth="lite"
Extract Parameters (NimbleExtractRetriever)
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key |
str | None |
None |
API key (or set NIMBLE_API_KEY) |
driver |
str | None |
None |
Browser driver: vx6, vx8, vx8-pro, vx10, vx10-pro, vx12, vx12-pro |
wait |
int | None |
None |
Render wait in milliseconds (uses browser_actions) |
locale |
str |
"en" |
Language/locale |
country |
str |
"US" |
Country code |
NimbleExtractTool
The extract tool accepts a single url parameter and returns the page content as a markdown string.
Response Formats
Document Structure (Retrievers)
Document(
page_content="Full content...",
metadata={
"title": "Page Title",
"url": "https://example.com",
"description": "Page description...",
"position": 1,
"entity_type": "organic" # or "answer"
}
)
Search Tool Response (JSON)
{
"results": [
{
"title": "Title",
"url": "https://...",
"description": "...",
"content": "Full content...",
"metadata": {
"position": 1,
"entity_type": "organic"
}
}
]
}
Extract Tool Response (String)
The extract tool returns a markdown string directly.
Best Practices
Search Depth Levels
Use search_depth="deep" for:
- RAG applications needing full context
- Content analysis and summarization
- In-depth research tasks
Use search_depth="lite" (default) for:
- Quick lookups
- Getting lists of URLs
- When you'll extract specific URLs later
Use search_depth="fast" for (Enterprise only):
- Production workloads needing rich content at low latency
Tools vs. Retrievers
Retrievers: Use in chains, RAG pipelines, vector store integration Tools: Use with agents that need dynamic search control
Filtering Tips
- Academic research:
include_domains=["edu", "scholar.google.com"] - Documentation:
include_domains=["docs.python.org", "readthedocs.io"] - Remove noise:
exclude_domains=["pinterest.com", "facebook.com"] - Recent news:
start_date="2024-01-01", focus="news" - Historical:
start_date="2020", end_date="2021"
Error Handling
The SDK handles retries automatically. For custom error handling:
from langchain_nimble import NimbleSearchRetriever
retriever = NimbleSearchRetriever()
try:
docs = retriever.invoke("query")
except ValueError as e:
print(f"API error: {e}")
Performance Tips
- Use async (
ainvoke) for concurrent requests - Request only needed results (
max_results) - Let API auto-select driver, or use lower driver levels (vx6/vx8) unless advanced rendering needed
- Avoid
waitparameter for static content
Examples & Documentation
- Examples: examples/
- API Docs: docs.nimbleway.com
- LangChain: python.langchain.com
Contributing
Contributions welcome! Please submit Pull Requests.
- Fork the repository
- Create feature branch (
git checkout -b feature/name) - Commit changes (
git commit -m 'Add feature') - Push branch (
git push origin feature/name) - Open Pull Request
Support
- Issues: GitHub Issues
- Docs: docs.nimbleway.com
- Website: nimbleway.com
License
MIT License - see LICENSE file for details.
Metadata
Release files for langchain-nimble 4.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| langchain_nimble-4.0.0.tar.gz | 224.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| langchain_nimble-4.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 259.5 kB
Release files / langchain_nimble-4.0.0.tar.gz
| Download URL | langchain_nimble-4.0.0.tar.gz |
|---|---|
| Size | 224.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f2194e6299ad74d276da76f77ab2e0be075dd0c4421cde596abcece2c0675e4e
|
|
BLAKE2b-256 checksum How to use checksums |
4295d74bfb737a861f77c02a72d48c23a3062556d9b27505a84daec6755beb64
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 30, 2026.
Transparency logRelease files / langchain_nimble-4.0.0-py3-none-any.whl
| Download URL | langchain_nimble-4.0.0-py3-none-any.whl |
|---|---|
| Size | 35.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d7cbe67c2c53f824b9c224f0f677659875ab2132cfae1c65eb1972b640b97800
|
|
BLAKE2b-256 checksum How to use checksums |
c9ef7bbf56c4a79c16dda93aa0354287b3a62cbe9345585b8a5984dc7cacee1b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 30, 2026.
Transparency log