Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 59 additions & 82 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ When one supported agent SDK is installed, the package detects it and creates to

## Supported agent SDKs

| SDK | Install extra / provider | Returned tool |
| SDK | Install extra | Returned tool |
|---------------------------|-----------------------------|------------------------------------------|
| OpenAI Agents SDK | `openai-agents` | OpenAI Agents `FunctionTool` |
| Pydantic AI | `pydantic-ai` | Pydantic AI `Tool` |
Expand Down Expand Up @@ -98,7 +98,7 @@ result = Runner.run_sync(
print(result.final_output)
```

## Quickstart: explicit LangChain provider
## Quickstart: LangChain

Install the LangChain extra and the model backend used by this example:

Expand All @@ -120,9 +120,9 @@ from serpapi_search_tools import maps_search, news_search, web_search
agent = create_agent(
model=ChatOpenAI(model="gpt-5.4-mini", temperature=0),
tools=[
web_search(provider="langchain"),
news_search(provider="langchain"),
maps_search(provider="langchain"),
web_search(),
news_search(),
maps_search(),
],
)

Expand All @@ -142,10 +142,8 @@ result = agent.invoke(
print(result["messages"][-1].content)
```

When LangChain is the only supported SDK installed, these constructors are also auto-detected, so `web_search()` is
enough. Supplying
`provider="langchain"` explicitly is useful when several supported SDKs share an environment or when you want the
integration choice to be visible in code.
The constructors use automatic SDK detection, just as in the first quickstart. For multi-SDK environments and explicit
selection, see [Agent SDKs](https://serpapi.github.io/serpapi-search-tools-python/user-guide/frameworks.html).

For a step-by-step explanation, keys, customization, and troubleshooting, read
the [detailed quickstart](https://serpapi.github.io/serpapi-search-tools-python/user-guide/quickstart.html).
Expand Down Expand Up @@ -196,9 +194,12 @@ tools = [
]
```

`news_search` supports keyword searches in Google News. `maps_search` searches Google Maps and accepts optional
`location`, `zoom` (`3` through `30`), and
`nearby` fields. Place details, reviews, and directions use different SerpApi APIs and are not part of this search tool.
`news_search` supports keyword searches in Google News. `maps_search` searches
Google Maps and accepts optional `location`, `zoom` (`3` through `30`), and
`nearby` fields. Use `nearby=True` for “near me” intent with a separate
`location`; leave it false when the query already names a city or area. Place
details, reviews, and directions use different SerpApi APIs and are not part of
this search tool.

### Shopping

Expand All @@ -219,60 +220,46 @@ The package routes one human `query` to each marketplace's native field:
Google Shopping uses `q`, Amazon uses `k`, Walmart uses `query`, and eBay uses
`_nkw`.

### Hotels
### Travel

```python
from serpapi_search_tools import hotels_search

hotels = hotels_search(provider="function")
result = hotels(
query="hotels in Kyoto",
check_in_date="2026-08-01",
check_out_date="2026-08-04",
adults=2,
children=1,
children_ages=[8],
)
from serpapi_search_tools import flights_search, hotels_search, travel_explore_search

travel_tools = [
hotels_search(),
flights_search(),
travel_explore_search(),
]
```

Hotel dates use `YYYY-MM-DD`. Checkout must be after check-in. When `children`
is nonzero, provide exactly one age from 1 through 17 per child.
These constructors create hotel, flight, and destination-discovery tools for the detected agent SDK.

### Flights
#### Hotels

```python
from serpapi_search_tools import TravelClass, flights_search

flights = flights_search(provider="function")
result = flights(
departure_id="LAX",
arrival_id="AUS",
outbound_date="2026-08-01",
return_date="2026-08-04",
travel_class=TravelClass.BUSINESS,
adults=1,
)
```

`flights_search` requires an origin, destination, and outbound date. Omitting
`return_date` creates a one-way request; including it creates a round trip. Multi-city searches are not currently
supported.
`hotels_search` lets the agent provide a destination, dates, and guest details. Hotel dates use `YYYY-MM-DD`. Checkout
must be after check-in. When `children`
is nonzero, provide exactly one age from 1 through 17 per child; use `1` for a
child under one year old.

### Explore destinations
#### Flights

```python
from serpapi_search_tools import travel_explore_search
`flights_search` lets the agent provide route, date, cabin, and passenger details. It requires an origin, destination,
and outbound date. Omitting
`return_date` creates a one-way request; including it creates a round trip.
Use specific airport IATA codes such as `LHR` and `CDG`, not metropolitan codes
such as `LON` and `PAR`. For a city-wide search, use a Google Knowledge Graph
location ID (KGMID) beginning with `/m/` or `/g/`, such as `/m/04jpl` for
London or `/m/05qtj` for Paris. Multi-city searches are not currently
supported.

explore = travel_explore_search(provider="function")
result = explore(
departure_id="JFK",
arrival_area_id="/m/02j9z",
)
```
#### Explore destinations

Travel Explore requires only a departure identifier. It can also accept an arrival identifier or area, fixed
outbound/return dates, cabin class, and passenger counts. These travel tools send their route and date fields directly
to the matching SerpApi endpoint.
`travel_explore_search` lets the agent discover destinations and requires only a departure airport IATA code or city
KGMID. It
can also accept a specific arrival airport or city through `arrival_id`, or a
region or country KGMID through `arrival_area_id`. Fixed outbound/return dates,
cabin class, and passenger counts are optional. These travel tools send their
route and date fields directly to the matching SerpApi endpoint.

## Set advanced parameters in application code

Expand All @@ -296,35 +283,24 @@ defaults. Reserved keys (`api_key`, `async`, `engine`, and `output`) are rejecte

## Handle search failures

The built-in client raises `SerpApiSearchError` when SerpApi rejects or cannot complete a request:

```python
from serpapi_search_tools import SerpApiSearchError, web_search

search = web_search(provider="function")
try:
result = search(query="Python packaging")
except SerpApiSearchError as exc:
print(f"Search failed: {exc}")
```

Local input errors such as invalid dates or incompatible parameters remain
`ValueError`, so applications can distinguish validation from provider and transport failures.
The search runtime raises `SerpApiSearchError` for SerpApi and transport failures. Invalid tool inputs raise
`ValueError`. Agent SDKs surface or handle tool errors differently, so use your SDK's normal tool-error mechanism. See
[Debugging](https://serpapi.github.io/serpapi-search-tools-python/user-guide/debugging.html) for detailed examples.

## Common factory options

Every constructor accepts:

| Option | Purpose |
|--------------------|-------------------------------------------------------------------------------------------------------------------|
| `provider` | Defaults to `"auto"`; select an SDK explicitly in multi-SDK environments or use `"function"` for a plain callable |
| `include_examples` | Include or omit a short example in the model description |
| `api_key` | Explicit SerpApi key |
| `client` | Custom object with `search(params)` for caching, interception, or tests |
| `default_params` | Application-controlled SerpApi options |
| `timeout` | Timeout passed to the SerpApi SDK client |
| `name` | Tool name presented to the model |
| `mode` | Result detail level: `"compact"` (default) or `"full"` |
| Option | Purpose |
|--------------------|-------------------------------------------------------------------------------------------------------|
| `provider` | Defaults to `"auto"`; select an SDK explicitly only when multiple supported SDKs share an environment |
| `include_examples` | Include or omit a short example in the model description |
| `api_key` | Explicit SerpApi key |
| `client` | Custom object with `search(params)` for caching, interception, or tests |
| `default_params` | Application-controlled SerpApi options |
| `timeout` | Timeout passed to the SerpApi SDK client |
| `name` | Tool name presented to the model |
| `mode` | Result detail level: `"compact"` (default) or `"full"` |

`web_search` and `shopping_search` additionally accept `allowed_engines` and
`default_engine`. The tool offers only the engine values you configured.
Expand All @@ -348,8 +324,9 @@ Every constructor accepts:
- [Google Flights](https://serpapi.com/google-flights-api)
- [Google Travel Explore](https://serpapi.com/google-travel-explore-api)

SerpApi's complete documentation index is available in
[`llms.txt`](https://serpapi.com/llms.txt).
For AI coding agents that need broader SerpApi API context, use
[SerpApi's agent-friendly documentation index (`llms.txt`)](https://serpapi.com/llms.txt). It links directly to Markdown
API references, including APIs beyond those wrapped by this package.

## More guides

Expand Down
6 changes: 3 additions & 3 deletions cookbook/pydantic-ai/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@

from dotenv import load_dotenv
from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.models.openai import OpenAIResponsesModel
from pydantic_ai.providers.openai import OpenAIProvider

from serpapi_search_tools import images_search, maps_search, web_search

load_dotenv()

MODEL = os.getenv("OPENAI_MODEL", "gpt-5.4-mini")
MODEL = os.getenv("OPENAI_MODEL", "gpt-5.6-luna")
PROMPT = os.getenv(
"COOKBOOK_PROMPT",
(
Expand Down Expand Up @@ -48,7 +48,7 @@ def _write_report(text: str) -> Path:
def main() -> None:
_require_serpapi_key()
provider = OpenAIProvider(api_key=_require_env("OPENAI_API_KEY"))
model = OpenAIChatModel(MODEL, provider=provider)
model = OpenAIResponsesModel(MODEL, provider=provider)
agent = Agent(
model,
instructions=(
Expand Down
91 changes: 83 additions & 8 deletions docs/cookbook/agno.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,93 @@ description: Combine category facts, launches, and live price signals.

# Agno market research

This agent analyzes a product category using durable facts, recent launches,
and current shopping listings, then writes a market report.
- **Agent pattern:** Bounded tool loop
- **Search surfaces:** Web, news, and shopping
- **Saved artifact:** `agno-market-research.md`

SerpApi enhancement: web, news, and shopping tools replace the upstream search
dependency while preserving the decision-focused market research goal.
## What you'll build

An Agno agent that assesses the US market for home espresso grinders under
USD 800. It separates durable category and manufacturer facts from recent
launches and time-sensitive marketplace signals, then writes a decision-ready
market report.

**Default brief:** Map the category, representative products, gaps, and risks.
Treat live price and availability as signals—not permanent product facts—and
include source URLs.

## How the agent works

1. **Frame the category.** Web search establishes segments, manufacturers, and
durable product facts.
2. **Check current signals.** News finds launches while shopping search captures
live prices and availability.
3. **Reconcile the market.** The agent compares the evidence, calls out gaps,
and stays within a ten-call tool budget.

## Core agent setup

This abridged excerpt keeps the Agno agent and tool boundary in view. The full
script also handles model configuration, environment validation, and Markdown
output.

```python
agent = Agent(
name="SerpApi market researcher",
model=model,
instructions=[
"Search before making market claims.",
"Use the most specific SerpApi tool for each question.",
"Separate live listing signals from durable category facts.",
],
tools=[
web_search(provider="agno", allowed_engines=["google_light", "bing"]),
news_search(provider="agno"),
shopping_search(provider="agno"),
],
markdown=True,
tool_call_limit=10,
)
response = agent.run(PROMPT)
```

[View the complete `main.py` →](https://github.com/serpapi/serpapi-search-tools-python/blob/main/cookbook/agno/main.py)

## Run the recipe

Set `SERPAPI_API_KEY` and `XAI_API_KEY` in the repository-root `.env`, then
run:

```bash
uv run --isolated --no-project --with 'serpapi-search-tools[agno]' --with python-dotenv cookbook/agno/main.py
```

Read the
[complete cookbook entry](https://github.com/serpapi/serpapi-search-tools-python/tree/main/cookbook/agno)
or Agno's official
[market research cookbook](https://github.com/agno-agi/agno/blob/main/cookbook/91_tools/parallel/market_research.py).
Optional controls: `XAI_MODEL`, `XAI_BASE_URL`, `COOKBOOK_PROMPT`, and
`COOKBOOK_OUTPUT_DIR`.

**Portable environment:** `--isolated --no-project` runs the local recipe
against the published `serpapi-search-tools[agno]` package instead of importing
this checkout.

## Inspect the result

The recipe writes `cookbook-output/agno-market-research.md`. Expect category
segments, representative products, current price signals, market gaps, risks,
and direct source URLs.

The same report is printed to the terminal. Set `COOKBOOK_OUTPUT_DIR` to move
the saved artifact, or `COOKBOOK_PROMPT` to research another category.

## SerpApi tools used

`web_search` supplies category and manufacturer facts, `news_search` tracks
recent launches, and `shopping_search` captures current prices and
availability. Keeping these result types separate helps the agent label which
signals are durable and which may change quickly.

**Framework pattern:** The agent structure is inspired by Agno's parallel
market research cookbook; this recipe applies it to three SerpApi evidence
surfaces.

- [Open the runnable recipe](https://github.com/serpapi/serpapi-search-tools-python/tree/main/cookbook/agno)
- [View Agno's source example](https://github.com/agno-agi/agno/blob/main/cookbook/91_tools/parallel/market_research.py)
Loading
Loading