Metadata-Version: 2.4
Name: strale-fallback
Version: 0.1.0
Summary: Automatic API fallback via Strale — when your primary API fails, Strale picks up the call
Project-URL: Homepage, https://strale.dev
Project-URL: Repository, https://github.com/strale-io/strale-fallback
Project-URL: Documentation, https://strale.dev/docs
Author-email: Strale <hello@strale.io>
License: MIT
License-File: LICENSE
Requires-Python: >=3.9
Requires-Dist: httpx>=0.24.0
Description-Content-Type: text/markdown

# strale-fallback

When your agent's primary API fails, Strale picks up the call.

`strale-fallback` wraps any function in your agent pipeline. When the primary call fails (timeout, 429, 503, malformed response), it automatically finds a matching Strale capability and executes it — returning structured JSON with a quality score.

## Install

```bash
pip install strale-fallback
```

## Usage

```python
import os
from strale_fallback import with_fallback

@with_fallback(
    task_description="validate IBAN number",
    strale_api_key=os.environ["STRALE_API_KEY"]
)
async def validate_iban(iban: str):
    # Your primary API call — if this fails, Strale takes over
    return await my_primary_api.validate_iban(iban)

result = await validate_iban("SE3550000000054910000003")
print(result.source)           # "primary" or "strale_fallback"
print(result.data)             # structured JSON either way
print(result.capability_used)  # e.g. "iban-validate" (if fallback used)
```

Sync functions work too:

```python
@with_fallback(task_description="check company sanctions")
def check_sanctions(company_name: str):
    return requests.get(f"https://my-api.com/sanctions/{company_name}").json()
```

## How it works

1. Your primary function is called normally
2. If it throws (any HTTP error, timeout, or exception), strale-fallback calls `POST /v1/suggest` with your `taskDescription` to find the best matching Strale capability
3. It executes that capability with your function's arguments as inputs
4. Returns a `FallbackResult` with `source: "strale_fallback"` so you know which path was taken

## FallbackResult

| Field | Type | Description |
|---|---|---|
| `success` | bool | Whether a result was obtained |
| `data` | any | The result data |
| `source` | string | `"primary"` or `"strale_fallback"` |
| `capability_used` | string? | Strale capability slug if fallback used |
| `strale_sqs` | float? | Quality score (0-100) if fallback used |
| `error` | string? | Error message if both paths failed |

## Quality threshold

```python
# Only use Strale as fallback if SQS quality score >= 80
@with_fallback(
    task_description="check company sanctions",
    min_sqs=80
)
async def check_sanctions(company: str): ...
```

## Environment

Set `STRALE_API_KEY` — or pass it directly to the decorator.
Get a free key with trial credits: https://strale.dev/signup

## Free capabilities (no key needed)

`iban-validate`, `email-validate`, `dns-lookup`, `json-repair`, `url-to-markdown` — these work even without an API key.

Full capability catalog: https://strale.dev/capabilities

## License

MIT
