agent-search-python 0.1.0
Python client for the Agent Search API.
Requires Python: >=3.13
Keywords: agent-search, agents, sdk

# Agent Search Python SDK

A Python client library for discovering and searching agents via the Agent Search service. This SDK enables applications and agents to discover other agents by semantic intent, apply hard constraints (country, capability, I/O modes), and retrieve agent cards for invocation.


## Installation

### Install from PyPI 

```bash
pip install agent-search-python
```

### Install locally in development mode

```bash
pip install -e /path/to/agent-search-python
```

### Uninstall

```bash
pip uninstall agent-search-python
```

## Requirements

- Python >= 3.13
- httpx >= 0.24.0
- pydantic >= 2.0.0

## Quick Start

### Basic Usage

```python
from agent_search import AgentSearchClient

# Create a client instance
client = AgentSearchClient()

# Search for agents
response = client.search("Convert USD to KES")

# Process results
if response.success:
    for agent in response.agents:
        print(f"Agent: {agent.agent_name}")
        print(f"Description: {agent.agent_description}")
        print(f"Card URL: {agent.agent_card_url}")
        print(f"Organization: {agent.organization_name}")
        print("---")
else:
    print(f"Error: {response.error}")

# Close the client when done
client.close()
```

### Using Context Manager

```python
from agent_search import AgentSearchClient

# Automatically closes the client when done
with AgentSearchClient() as client:
    response = client.search("Analyze a power purchase agreement")
    
    if response.success:
        print(f"Found {len(response.agents)} agents")
```

### Advanced Search with Filters

```python
from agent_search import AgentSearchClient

client = AgentSearchClient()

# Search with multiple filters
response = client.search(
    query="Currency conversion service",
    max_result=5,
    country="KE",  # Kenya
    capability="streaming",  # Agent must support streaming
    default_input_mode="text",
    default_output_mode="text"
)

client.close()
```

### With API Key Authentication

```python
from agent_search import AgentSearchClient

client = AgentSearchClient(api_key="your-api-key-here")

response = client.search("Find weather agents")

client.close()
```

## API Reference

### AgentSearchClient

The main client class for interacting with the Agent Search service.

#### Constructor

```python
AgentSearchClient(
    retries: int = 2,
    api_key: Optional[str] = None
)
```

**Parameters:**
- `retries` (int, optional): Number of retry attempts for failed requests. Defaults to 2.
- `api_key` (str, optional): API key for authentication. If provided, will be sent as a Bearer token.

#### Methods

##### `search()`

Discover agents that can best handle a given query.

```python
search(
    query: str,
    *,
    max_result: Optional[int] = None,
    country: Optional[str] = None,
    capability: Optional[Literal["streaming", "push_notification"]] = None,
    default_input_mode: Optional[Literal["text", "voice", "image", "video"]] = None,
    default_output_mode: Optional[Literal["text", "voice", "image", "video"]] = None,
) -> SearchResponse
```

**Parameters:**
- `query` (str, required): Natural language description of the task to be handled.
  - Example: `"Convert USD to KES"` or `"Analyze a power purchase agreement"`
- `max_result` (int, optional): Maximum number of agents to return. Defaults to 2.
- `country` (str, optional): ISO country name or code of the agent's organization.
  - Example: `"KE"`, `"Kenya"`
- `capability` (str, optional): Capability that the agent must support.
  - `"streaming"`: Agent can stream partial responses
  - `"push_notification"`: Agent can send async notifications
- `default_input_mode` (str, optional): Primary input modality the agent must support.
  - Options: `"text"`, `"voice"`, `"image"`, `"video"`
- `default_output_mode` (str, optional): Primary output modality the agent must support.
  - Options: `"text"`, `"voice"`, `"image"`, `"video"`

**Returns:**
- `SearchResponse`: A response object containing matching agents and their details.

##### `close()`

Close the HTTP client and release resources. Should be called when done with the client.

```python
client.close()
```

#### Context Manager Support

The client supports Python's context manager protocol for automatic resource cleanup:

```python
with AgentSearchClient() as client:
    # Use client here
    pass
# Client is automatically closed
```

### Models

#### SearchResponse

Response object returned by the `search()` method.

```python
class SearchResponse:
    success: bool  # Whether the request succeeded
    agents: List[AgentDetails]  # List of matching agents
    error: Optional[str]  # Error message if request failed
```

#### AgentDetails

Details about a discovered agent.

```python
class AgentDetails:
    agent_name: Optional[str]  # Name of the agent
    agent_description: Optional[str]  # Description of the agent
    agent_card_url: Optional[str]  # URL of the agent's card for invocation
    organization_name: Optional[str]  # Name of the organization
    organization_url: Optional[str]  # URL of the organization
```

## Configuration

The client uses default configuration that can be customized by modifying the `ClientConfig` class:

- **Base URL**: `http://127.0.0.1:8000` (default)
- **Timeout**: `60.0` seconds
- **Retries**: `2` attempts
- **User Agent**: `agent-search-sdk/0.0.1`

To use a different base URL or configuration, you can modify the `ClientConfig` in `agent_search/config.py` or extend the client class.

## Error Handling

The SDK provides several error types for different failure scenarios:

### Error Types

- `SdkError`: Base class for all SDK errors
- `HttpStatusError`: Raised when the API returns an HTTP error status (4xx, 5xx)
  - Attributes: `status_code`, `body`
- `NetworkError`: Raised when a network error occurs
- `TimeoutError`: Raised when a request times out
- `InvalidResponseError`: Raised when the response is not valid JSON

### Example Error Handling

```python
from agent_search import AgentSearchClient
from agent_search.errors import HttpStatusError, NetworkError, TimeoutError

client = AgentSearchClient()

try:
    response = client.search("test query")
except HttpStatusError as e:
    print(f"HTTP Error {e.status_code}: {e}")
    print(f"Response body: {e.body}")
except NetworkError as e:
    print(f"Network error: {e}")
except TimeoutError as e:
    print(f"Request timed out: {e}")
finally:
    client.close()
```

## Examples

### Example 1: Simple Agent Discovery

```python
from agent_search import AgentSearchClient

with AgentSearchClient() as client:
    response = client.search("Find payment processing agents")
    
    if response.success and response.agents:
        print(f"Found {len(response.agents)} agents:")
        for agent in response.agents:
            print(f"- {agent.agent_name}: {agent.agent_description}")
```

### Example 2: Filtered Search

```python
from agent_search import AgentSearchClient

client = AgentSearchClient()

# Find streaming-capable text agents in Kenya
response = client.search(
    query="Financial services",
    country="KE",
    capability="streaming",
    default_input_mode="text",
    default_output_mode="text",
    max_result=10
)

if response.success:
    for agent in response.agents:
        print(f"{agent.agent_name} - {agent.organization_name}")
        print(f"Card: {agent.agent_card_url}")

client.close()
```

### Example 3: Error Handling

```python
from agent_search import AgentSearchClient
from agent_search.errors import SdkError

client = AgentSearchClient(api_key="your-key")

try:
    response = client.search("test")
    
    if not response.success:
        print(f"Search failed: {response.error}")
    else:
        print(f"Success! Found {len(response.agents)} agents")
        
except SdkError as e:
    print(f"SDK Error: {e}")
finally:
    client.close()
```

## Development

### Project Structure

```
agent-search-python/
├── agent_search/
│   ├── __init__.py          # Package exports
│   ├── _version.py          # Package version (managed by Hatch)
│   ├── client.py            # Main client class
│   ├── config.py            # Client configuration
│   ├── models.py            # Pydantic models
│   ├── transport.py         # HTTP transport layer
│   └── errors.py            # Error classes
├── pyproject.toml           # Project configuration (Hatch)
└── README.md                # This file
```

### Building & Publishing with Hatch

Hatch drives builds and publishes to PyPI/TestPyPI:

```bash
# install hatch (one-time)
pip install --user hatch

# bump the version stored in agent_search/_version.py
hatch version minor  # or patch/major

# build sdists and wheels into dist/
hatch build

# publish (set PYPi creds in ~/.pypirc or env vars)
hatch publish -r test-pypi  # dry-run to TestPyPI
hatch publish               # push to PyPI
```

### Running Tests

```bash
# Add test commands here when tests are added
pytest
```

## License

[Add your license information here]

## Contributing

[Add contributing guidelines here]

## Support

[Add support information here]

## Changelog

### Version 0.1.0
- Initial release
- Basic agent search functionality
- Support for filtering by country, capability, and I/O modes
- Automatic retry logic
- Comprehensive error handling