> ## 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.

# Tool Registry Proxy

> Discover and call hundreds of third-party API endpoints through one token, with vendor credentials injected server-side

The registry proxy connector lets an agent discover and call a large catalogue of third-party API endpoints (SEO, enrichment, social data, scraping, ads) through a single token — vendor credentials are injected server-side by the registry, so the agent never holds keys.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Registry Proxy"
        A[Agent] --> S[registry_search]
        A --> D[registry_describe]
        A --> C[registry_call]
        C --> P[Registry Proxy]
        P --> V[Vendor API]
    end

    classDef agent fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef tool fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef out fill:#10B981,stroke:#7C90A0,color:#fff

    class A agent
    class S,D,C tool
    class P tool
    class V out
```

> [!NOTE]
>
> **Bring your own account.** PraisonAI ships no registry code and no default endpoint. You supply your own account token or a self-hosted base URL. The connector is disabled until `TOOL_PROXY_URL` is set.

## Quick Start

**1. Install and configure**

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
pip install 'praisonai-tools[registry-proxy]'
export TOOL_PROXY_URL=http://127.0.0.1:18790   # your hosted or self-hosted registry
export TOOL_PROXY_TOKEN=your-token
export TOOL_PROXY_AUTH_HEADER=X-Treg-Token      # treg wire format; omit for Bearer
```

**2. Give the three functions to an agent**

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent
from praisonai_tools.registry_proxy import registry_search, registry_describe, registry_call

agent = Agent(
    instructions="Find and use external APIs via the tool registry.",
    tools=[registry_search, registry_describe, registry_call],
)
agent.start("Enrich the person behind alice@example.com and summarise who they are.")
```

The agent searches the catalogue, describes a matching endpoint, then calls it — one token, no vendor keys in the agent.

***

## How It Works

The connector exposes three functions over the registry's plain-HTTP surface.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Agent
    participant Proxy as Registry Proxy
    participant Vendor

    User->>Agent: "Enrich alice@example.com"
    Agent->>Proxy: registry_search("enrich a person from an email")
    Proxy-->>Agent: catalogue matches
    Agent->>Proxy: registry_describe("diffbot.people.enrich")
    Proxy-->>Agent: params, price-per-call, method, example
    Agent->>Proxy: registry_call("diffbot.people.enrich", {...})
    Proxy->>Vendor: request + injected credential
    Vendor-->>Proxy: result
    Proxy-->>Agent: result
    Agent-->>User: summary
```

| Function | Cost | Purpose |
| - | - | - |
| `registry_search(query)` | free | Capability search over the catalogue |
| `registry_describe(tool_id)` | free | Params, price-per-call, HTTP method, example response |
| `registry_call(tool_id, params)` | paid | Invoke via proxy; credential injected server-side |

The registry HTTP routes the connector talks to:

| Route | Purpose |
| - | - |
| `GET /catalog/search?q={query}` | Free catalogue search |
| `GET /catalog/endpoints/{id}` | Free endpoint doc (nested under `endpoint`, with a structured `cost` object) |
| `{METHOD} /call/{id}` | Proxied paid call — the registry enforces the endpoint's declared HTTP method |
| `POST /tools` | Register your own upstream endpoint (public https only; loopback/private upstreams are refused by the SSRF guard) |

***

## Self-Hosting the Registry

[treg](https://github.com/superdesigndev/treg) is an external, self-hostable tool registry. These are the exact steps to stand up a local registry for testing.

**1. Clone treg**

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
git clone https://github.com/superdesigndev/treg
cd treg
```

**2. Install (Python 3.12–3.13)**

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# If your default python is older, use uv:
uv sync --extra server --python 3.13
```

**3. Boot the server**

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Default port 18790. Optionally point it at a sqlite file:
TREG_DATABASE_URL="sqlite+aiosqlite:////tmp/treg.db" .venv/bin/python -m treg
# server is now on http://127.0.0.1:18790
```

**4. Mint an API token**

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
curl -X POST http://127.0.0.1:18790/users \
  -H 'Content-Type: application/json' \
  -d '{"email": "you@example.com"}'
# -> {"token": "..."}  — save this
```

Auth on all authenticated routes is the raw token in the **`X-Treg-Token`** header — set `TOOL_PROXY_AUTH_HEADER=X-Treg-Token` so the connector sends the raw token instead of `Bearer {token}`.

***

## The Three Functions

Each function is an agent tool that defaults to the `TOOL_PROXY_URL` / `TOOL_PROXY_TOKEN` environment variables.

### registry\_search

Free capability search returning catalogue matches for a natural-language query.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai_tools.registry_proxy import registry_search

registry_search("enrich a person from an email address")
# {'query': ..., 'count': 2, 'results': [{'id': 'hunter.x.combined', ...}, ...]}
```

### registry\_describe

Free read returning an endpoint's parameters, HTTP method, price-per-call and an example response.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai_tools.registry_proxy import registry_describe

registry_describe("diffbot.people.enrich")
# {'endpoint': {'id': ..., 'method': 'GET',
#   'cost': {'value': 25, 'currency': 'credit', 'usd': 0.0299}, ...}}
```

### registry\_call

Paid invoke. The registry injects the upstream vendor credential server-side. The HTTP method is auto-derived from the describe doc; GET params are sent as the query string, POST/PUT as a JSON body.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai_tools.registry_proxy import registry_call

registry_call("diffbot.people.enrich", params={"type": "person", "email": "a@b.co"})
# method auto-derived as GET from the describe doc; params sent as query string
```

***

## Configuration Options

Configure the connector with environment variables (zero-code) or per-call keyword arguments.

### Environment Variables

| Variable | Default | Description |
| - | - | - |
| `TOOL_PROXY_URL` | unset (connector disabled) | Registry base URL |
| `TOOL_PROXY_TOKEN` | unset | Proxy auth token |
| `TOOL_PROXY_AUTH_HEADER` | `Authorization` | Header carrying the token. `Authorization` sends `Bearer {token}`; any other name (e.g. `X-Treg-Token`) sends the raw token |
| `TOOL_PROXY_DESCRIBE_PATH` | `/catalog/endpoints/{tool_id}` | Describe-route template; must contain `{tool_id}`. Override for registries with a different path shape |

### Constructor / Per-Call Options

`RegistryProxyTool` accepts these options; the same names work as optional keyword arguments on `registry_search`, `registry_describe` and `registry_call`.

| Option | Type | Default | Description |
| - | - | - | - |
| `proxy_url` | `str` | env `TOOL_PROXY_URL` | Registry base URL |
| `token` | `str` | env `TOOL_PROXY_TOKEN` | Auth token (see security note) |
| `timeout` | `float` | `60.0` | HTTP timeout in seconds |
| `max_cost_per_call` | `float` | `None` | Deny + report any call whose per-call price exceeds this (USD) |
| `max_session_spend` | `float` | `None` | Deny + report any call that would push cumulative session spend past this (USD); tracked per `(proxy_url, token)` pair |
| `auth_header` | `str` | env / `Authorization` | Header carrying the token |
| `method` | `str` | auto-derived | `registry_call` only. HTTP method for the endpoint. When omitted, derived from the describe doc; explicit values are validated against GET/POST/PUT/PATCH/DELETE |
| `describe_path` | `str` | env / `/catalog/endpoints/{tool_id}` | Describe-route template; must contain `{tool_id}` |

***

## Spend Guards

`registry_call` accepts optional budget guards that deny and report a call as a tool-result error before any money is spent.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai_tools.registry_proxy import registry_call

registry_call(
    "diffbot.people.enrich",
    params={"type": "person", "email": "a@b.co"},
    max_cost_per_call=0.05,   # never pay more than 5 cents for one call
    max_session_spend=1.00,   # hard $1 ceiling for the whole session
)
# over budget -> {'error': 'Denied: price per call 0.0299 exceeds max_cost_per_call ...'}
```

| Parameter | Type | Default | Description |
| - | - | - | - |
| `max_cost_per_call` | `float` | `None` | Deny the call if its price-per-call exceeds this value |
| `max_session_spend` | `float` | `None` | Deny the call if it would push cumulative spend past this value |

* Per-call price is read from `registry_describe`, so guards work without vendor-specific configuration.
* Guards **fail closed**: if a budget is set but the price cannot be read (or is non-finite/negative), the call is denied.
* `max_session_spend` persists across separate `registry_call` invocations in the same process, scoped per `(proxy_url, token)` so distinct accounts never share a budget.

***

## Security Model

The connector is designed so a prompt-injected agent cannot leak the proxy token or spend uncontrolled money.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    subgraph "Token Attachment"
        E[Env-derived URL] -->|attaches| T[TOOL_PROXY_TOKEN]
        A[Agent-supplied proxy_url] -.->|never attached| T
    end

    classDef safe fill:#10B981,stroke:#7C90A0,color:#fff
    classDef danger fill:#8B0000,stroke:#7C90A0,color:#fff

    class E safe
    class A danger
    class T safe
```

> [accordion] Credentials injected server-side
>
> The registry injects the upstream vendor credential — the agent only ever holds the single proxy token, never vendor keys.

> [accordion] Token-trust rule
>
> The env `TOOL_PROXY_TOKEN` is attached **only** when the URL is also env-derived. If an agent supplies `proxy_url` at call time, the ambient token is **not** sent — a prompt-injected agent cannot exfiltrate the token to an attacker-controlled endpoint.

> [accordion] Spend guards fail closed
>
> If a price cannot be read (or is non-finite/negative), a guarded call is denied rather than allowed.

> [accordion] Errors returned, never raised
>
> Auth, insufficient-balance, upstream and timeout failures are returned as `{"error": ...}` tool results, so a failed call never crashes the agent.

***

## Examples

### Direct three-step flow (no agent)

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai_tools.registry_proxy import registry_search, registry_describe, registry_call

hits = registry_search("enrich a person from an email address")
# {'query': ..., 'count': 2, 'results': [{'id': 'hunter.x.combined', ...}, ...]}

doc = registry_describe("diffbot.people.enrich")
# {'endpoint': {'id': ..., 'method': 'GET',
#   'cost': {'value': 25, 'currency': 'credit', 'usd': 0.0299}, ...}}

result = registry_call("diffbot.people.enrich", params={"type": "person", "email": "a@b.co"})
# method auto-derived as GET from the describe doc; params sent as query string
```

### Explicit method and class form

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai_tools.registry_proxy import RegistryProxyTool

t = RegistryProxyTool(auth_header="X-Treg-Token", max_session_spend=2.0)
t.run(action="search", query="weather forecast")
t.run(action="describe", tool_id="{tool-id}")
t.run(action="call", tool_id="{tool-id}", params={"q": "London"}, method="GET")
```

### Different registry wire-format (non-treg deployment)

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai_tools.registry_proxy import RegistryProxyTool

t = RegistryProxyTool(
    auth_header="Authorization",              # Bearer token style
    describe_path="/api/v1/tools/{tool_id}",  # custom describe route
)
```

***

## Troubleshooting

> [accordion] Connector disabled (URL unset)
>
> If `TOOL_PROXY_URL` is unset, every call returns: `Tool registry proxy is not configured. Set TOOL_PROXY_URL (and optionally TOOL_PROXY_TOKEN) to enable the connector.`

> [accordion] httpx not installed
>
> Calls return `httpx not installed. Install with: pip install 'praisonai-tools[registry-proxy]'`. Install the extra to add `httpx`.

> [accordion] 404 on describe (wrong path)
>
> A 404 on `registry_describe` usually means the deployment uses a different describe route. Set `TOOL_PROXY_DESCRIBE_PATH` (or pass `describe_path`) to the correct template — it must contain `{tool_id}`.

> [accordion] Endpoint is GET — add method
>
> Current main auto-derives the HTTP method from the describe doc. Older installs may reject a mislabelled verb; pass `method="GET"` (or the endpoint's declared method) explicitly to `registry_call`.

> [accordion] Marketplace-credential 404
>
> A message like "no {provider} credential in this org" means the registry org has no vendor key connected — connect one on the registry side.

> [accordion] SSRF-guard refusals
>
> Registering an upstream (`POST /tools`) with a loopback or private address is refused by the registry's SSRF guard by design — use a public https upstream.

> [accordion] Error shapes
>
> All failures come back as `{"error": ...}` tool results: authentication failed (HTTP 401/403), insufficient balance (HTTP 402), upstream 4xx/5xx passed through, and request timeouts.

***

## Related

> [card] [Tools Overview](https://praison.ai/docs/tools/tools.md)
>
> Browse PraisonAI tool documentation

> [card] [Custom Tools](https://praison.ai/docs/tools/custom.md)
>
> Build your own agent tools


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.