> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Search

> Web search via DuckDuckGo, backed by the ddgs package

`search` runs a real DuckDuckGo query and raises when the backend fails, so missing dependencies and rate limits are visible instead of silent.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Search Capability"
        A[🔎 search query] --> B[🦆 DuckDuckGo]
        B --> C[✅ Results]
        B --> D[⚠️ RuntimeError]
    end

    classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff
    classDef warn fill:#F59E0B,stroke:#7C90A0,color:#fff

    class A input
    class B process
    class C output
    class D warn
```

<Note>
  `search` needs the `ddgs` package at runtime. Install it with `pip install ddgs`.
</Note>

## Quick Start

<Steps>
  <Step title="Search from an Agent">
    Give an agent the web search tool for research tasks.

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent
    from praisonaiagents.tools import internet_search

    agent = Agent(
        name="Researcher",
        instructions="Search the web and summarise findings",
        tools=[internet_search]
    )

    agent.start("Find the latest news on the PraisonAI framework")
    ```
  </Step>

  <Step title="Direct capability call">
    Call `search` directly when you just need raw results.

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonai.capabilities import search

    result = search("PraisonAI framework")

    for r in result.results:
        print(r["title"], r["url"])
    ```
  </Step>
</Steps>

<Warning>
  If `ddgs` is missing or the provider rate-limits, `search` raises `RuntimeError` instead of returning an empty result. Earlier releases silently returned `total=0` — that behaviour is gone.
</Warning>

***

## How It Works

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Search as search()
    participant DDG as DuckDuckGo (ddgs)

    User->>Search: search("query")
    Search->>DDG: internet_search(query, max_results)
    alt success
        DDG-->>Search: results
        Search-->>User: SearchResult
    else missing ddgs or rate limit
        DDG-->>Search: {"error": "..."}
        Search-->>User: raise RuntimeError
    end
```

`search` calls `internet_search` under the hood. Each result is a dict with `title`, `url`, and `snippet` keys.

***

## Configuration Options

| Parameter     | Type        | Default  | Description                        |
| ------------- | ----------- | -------- | ---------------------------------- |
| `query`       | `str`       | Required | Search query                       |
| `sources`     | `List[str]` | `None`   | Optional list of sources to search |
| `max_results` | `int`       | `10`     | Maximum number of results          |
| `timeout`     | `float`     | `600.0`  | Request timeout in seconds         |
| `metadata`    | `Dict`      | `None`   | Optional metadata for tracing      |

`SearchResult` fields: `results` (list of dicts), `query`, `total`, `metadata`.

<Card title="Capabilities SDK Reference" icon="code" href="/docs/sdk/reference/praisonai/modules/capabilities">
  Auto-generated reference for the capabilities module
</Card>

***

## Common Patterns

Handle a missing dependency gracefully:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.capabilities import search

try:
    result = search("open source LLM agents")
    print(f"{result.total} results")
except RuntimeError as e:
    print(f"Search unavailable: {e}")
    # e.g. install ddgs: pip install ddgs
```

Async search delegates to the sync path:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import asyncio
from praisonai.capabilities import asearch

async def main():
    result = await asearch("vector databases")
    for r in result.results:
        print(r["title"])

asyncio.run(main())
```

***

## Best Practices

<AccordionGroup>
  <Accordion title="Install ddgs before using search">
    Run `pip install ddgs`. Without it, `search` raises `RuntimeError`.
  </Accordion>

  <Accordion title="Catch RuntimeError">
    Rate limits and missing dependencies surface as `RuntimeError`. Wrap calls so your app degrades gracefully instead of crashing.
  </Accordion>

  <Accordion title="Tune max_results">
    Lower `max_results` for faster, cheaper queries; raise it when you need broader coverage.
  </Accordion>
</AccordionGroup>

***

## Related

<CardGroup cols={2}>
  <Card title="Web Search Tools" icon="globe" href="/docs/tools/web-search">
    Search tools for agents
  </Card>

  <Card title="Capabilities Overview" icon="bolt" href="/docs/capabilities/index">
    All LiteLLM parity capabilities
  </Card>
</CardGroup>
