Metadata-Version: 2.4
Name: smart-agenthub
Version: 0.1.0
Summary: Python SDK and CLI for Agent Hub
Author: Agent Hub SDK Maintainers
License: Proprietary
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: click<9,>=8.1
Requires-Dist: httpx<1,>=0.27
Provides-Extra: dev
Requires-Dist: build<2,>=1.2; extra == 'dev'
Requires-Dist: mypy<2,>=1.14; extra == 'dev'
Requires-Dist: pytest-asyncio<2,>=0.25; extra == 'dev'
Requires-Dist: pytest-cov<7,>=6; extra == 'dev'
Requires-Dist: pytest<9,>=8.3; extra == 'dev'
Requires-Dist: ruff<1,>=0.9; extra == 'dev'
Description-Content-Type: text/markdown

# smart-agenthub

Python SDK and CLI for managing knowledge bases and Agents, and for invoking a
published Agent from an application.

## Requirements

- Python 3.10 or newer
- An Agent Hub server URL
- An API Key for management workflows, or an Agent Key for application calls

## Install

```bash
python -m pip install smart-agenthub
```

Pin a version for reproducible deployments:

```bash
python -m pip install smart-agenthub==0.1.0
```

## Management Client

Use `AgentHubClient` to configure models, knowledge bases, documents, Agents,
credentials and sessions.

```python
import os

from smart_agenthub import AgentHubClient

with AgentHubClient(
    os.environ["AGENTHUB_BASE_URL"],
    api_key=os.environ["AGENTHUB_API_KEY"],
    timeout=30.0,
    max_retries=2,
) as client:
    agents = client.agents.list()
    knowledge_bases = client.knowledge_bases.list()
```

The client accepts either `api_key` or `token`, never both. API Keys are intended
for long-lived automation. `token` is available only when the caller already owns
a short-lived bearer token; the SDK does not implement account login or captcha.

## Knowledge-base Workflow

```python
import os
import uuid

from smart_agenthub import AgentHubClient

with AgentHubClient(
    os.environ["AGENTHUB_BASE_URL"],
    api_key=os.environ["AGENTHUB_API_KEY"],
) as client:
    kb = client.knowledge_bases.create(
        body={
            "name": "Product documentation",
            "index_mode": "KEYWORD",
        }
    )
    upload = client.documents.upload(
        kb["id"],
        "guide.pdf",
        idempotency_key=str(uuid.uuid4()),
    )
    document = client.wait_for_document(
        upload["document"]["id"],
        timeout=900,
    )
```

For semantic or hybrid retrieval, select a ready embedding space when creating the
knowledge base. Use `wait_for_rebuild()` after changing index capabilities through a
rebuild request.

## Application Client

`AgentClient` requires one published Agent ID and its Agent Key. It cannot call
management APIs.

### Non-streaming response

```python
import os
import uuid

from smart_agenthub import AgentClient

with AgentClient(
    os.environ["AGENTHUB_BASE_URL"],
    agent_id=os.environ["AGENTHUB_AGENT_ID"],
    api_key=os.environ["AGENTHUB_AGENT_API_KEY"],
) as agent:
    response = agent.chat(
        [{"role": "user", "content": "What changed in the latest guide?"}],
        idempotency_key=str(uuid.uuid4()),
        stream=False,
    )
```

### Streaming response

```python
with AgentClient(
    os.environ["AGENTHUB_BASE_URL"],
    agent_id=os.environ["AGENTHUB_AGENT_ID"],
    api_key=os.environ["AGENTHUB_AGENT_API_KEY"],
) as agent:
    for event in agent.chat(
        [{"role": "user", "content": "Summarize the onboarding guide."}]
    ):
        if event.data == "[DONE]":
            break
        print(event.data)
```

Retain the returned `session_id`, `turn_id` and latest SSE event ID. If a stream
disconnects, inspect the turn with `get_turn()` and continue with
`resume(turn_id, last_event_id=...)`. Do not create a second turn solely because the
original stream disconnected.

`upload()` attaches a local file to an Agent conversation. Pass the returned file
reference in `attachments` on a later `chat()` call.

## Async Clients

`AsyncAgentHubClient` and `AsyncAgentClient` expose matching resources and methods.
Streaming methods return async iterators.

```python
import asyncio
import os

from smart_agenthub import AsyncAgentHubClient


async def main() -> None:
    async with AsyncAgentHubClient(
        os.environ["AGENTHUB_BASE_URL"],
        api_key=os.environ["AGENTHUB_API_KEY"],
    ) as client:
        print(await client.agents.list())


asyncio.run(main())
```

## CLI

The package installs `agenthub`.

```bash
agenthub login --base-url https://agent.example.com
agenthub whoami

agenthub agents list
agenthub knowledge-bases list
agenthub documents upload <kb-id> ./guide.pdf \
  --idempotency-key upload-guide-001

agenthub --json agent chat \
  --agent-id "$AGENTHUB_AGENT_ID" \
  --agent-key "$AGENTHUB_AGENT_API_KEY" \
  --message "Summarize the onboarding guide."

agenthub logout
```

`login` validates and saves an API Key in `~/.agenthub/credentials.json`; it does
not perform account login or create a bearer token. The credential directory and
file use private permissions and writes are atomic. Agent Keys and short-lived
bearer tokens are never saved.

For non-interactive use, configure:

```bash
export AGENTHUB_BASE_URL=https://agent.example.com
export AGENTHUB_API_KEY='<management-api-key>'
```

Global `--json` produces one JSON value for normal commands, `null` for empty
responses, JSON Lines for streams and a structured error object on stderr.

## Errors

All SDK exceptions inherit from `AgentHubError`. HTTP failures are mapped to typed
exceptions such as `AuthenticationError`, `PermissionDeniedError`, `NotFoundError`,
`ConflictError`, `ValidationError`, `RateLimitError` and `ServerError`.

```python
from smart_agenthub import AgentHubError, RateLimitError

try:
    result = client.agents.list()
except RateLimitError as exc:
    print(exc.retry_after, exc.request_id)
except AgentHubError as exc:
    print(str(exc))
```

API errors expose `status_code`, `code`, `request_id`, `retry_after` and `details`
when supplied by the server. Exception messages do not contain credentials or raw
secret-bearing response bodies.

## Naming and Return Values

- Resource methods use `snake_case`.
- JSON request and response keys keep their wire names.
- Business methods return the response envelope's `data` value.
- HTTP 204 operations return `None`.
- Pagination remains explicit; callers choose page boundaries.

The complete endpoint, parameter, request and response schemas are maintained in
the portable API reference distributed with the source repository.
