ralio 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ralio-0.1.0/.github/CODEOWNERS +8 -0
- ralio-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +47 -0
- ralio-0.1.0/.github/ISSUE_TEMPLATE/config.yml +8 -0
- ralio-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +25 -0
- ralio-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +21 -0
- ralio-0.1.0/.github/dependabot.yml +16 -0
- ralio-0.1.0/.github/workflows/ci.yml +24 -0
- ralio-0.1.0/.github/workflows/release.yml +43 -0
- ralio-0.1.0/.gitignore +25 -0
- ralio-0.1.0/.pre-commit-config.yaml +16 -0
- ralio-0.1.0/CHANGELOG.md +28 -0
- ralio-0.1.0/CODE_OF_CONDUCT.md +46 -0
- ralio-0.1.0/CONTRIBUTING.md +57 -0
- ralio-0.1.0/LICENSE +21 -0
- ralio-0.1.0/PKG-INFO +210 -0
- ralio-0.1.0/README.md +181 -0
- ralio-0.1.0/SECURITY.md +37 -0
- ralio-0.1.0/examples/quickstart.py +47 -0
- ralio-0.1.0/pyproject.toml +55 -0
- ralio-0.1.0/src/ralio/__init__.py +59 -0
- ralio-0.1.0/src/ralio/_crypto.py +161 -0
- ralio-0.1.0/src/ralio/_store.py +105 -0
- ralio-0.1.0/src/ralio/auth.py +111 -0
- ralio-0.1.0/src/ralio/client.py +131 -0
- ralio-0.1.0/src/ralio/errors.py +106 -0
- ralio-0.1.0/src/ralio/py.typed +0 -0
- ralio-0.1.0/src/ralio/registration.py +225 -0
- ralio-0.1.0/src/ralio/resources/__init__.py +11 -0
- ralio-0.1.0/src/ralio/resources/agents.py +21 -0
- ralio-0.1.0/src/ralio/resources/chat.py +81 -0
- ralio-0.1.0/src/ralio/resources/payment_intents.py +34 -0
- ralio-0.1.0/src/ralio/resources/transactions.py +31 -0
- ralio-0.1.0/src/ralio/transport.py +151 -0
- ralio-0.1.0/src/ralio/types.py +247 -0
- ralio-0.1.0/tests/conftest.py +43 -0
- ralio-0.1.0/tests/test_client.py +316 -0
- ralio-0.1.0/tests/test_crypto.py +81 -0
- ralio-0.1.0/tests/test_registration.py +188 -0
- ralio-0.1.0/tests/test_zero_config.py +85 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Default owners for everything in the repo.
|
|
2
|
+
* @lgrosales
|
|
3
|
+
|
|
4
|
+
# Security-sensitive crypto and auth lifecycle get explicit ownership.
|
|
5
|
+
/src/ralio/_crypto.py @lgrosales
|
|
6
|
+
/src/ralio/auth.py @lgrosales
|
|
7
|
+
/src/ralio/transport.py @lgrosales
|
|
8
|
+
/src/ralio/registration.py @lgrosales
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Report a problem with the Ralio Python SDK
|
|
3
|
+
labels: ["bug"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for reporting a bug. **Do not include private keys, access
|
|
9
|
+
tokens, or registration tickets** in this issue. For security
|
|
10
|
+
vulnerabilities, see [SECURITY.md](../../SECURITY.md) instead.
|
|
11
|
+
- type: textarea
|
|
12
|
+
id: what-happened
|
|
13
|
+
attributes:
|
|
14
|
+
label: What happened?
|
|
15
|
+
description: A clear description of the bug, including the full traceback if any.
|
|
16
|
+
placeholder: When I call client.chat.send(...), I get ...
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: reproduce
|
|
21
|
+
attributes:
|
|
22
|
+
label: Steps to reproduce
|
|
23
|
+
description: A minimal code snippet that triggers the issue (redact secrets).
|
|
24
|
+
render: python
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
- type: input
|
|
28
|
+
id: sdk-version
|
|
29
|
+
attributes:
|
|
30
|
+
label: SDK version
|
|
31
|
+
placeholder: "0.1.0 (python -c 'import ralio; print(ralio.__version__)')"
|
|
32
|
+
validations:
|
|
33
|
+
required: true
|
|
34
|
+
- type: input
|
|
35
|
+
id: python-version
|
|
36
|
+
attributes:
|
|
37
|
+
label: Python version
|
|
38
|
+
placeholder: "3.12"
|
|
39
|
+
validations:
|
|
40
|
+
required: true
|
|
41
|
+
- type: textarea
|
|
42
|
+
id: extra
|
|
43
|
+
attributes:
|
|
44
|
+
label: Anything else?
|
|
45
|
+
description: OS, networking setup (proxies), or other context.
|
|
46
|
+
validations:
|
|
47
|
+
required: false
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Security vulnerability
|
|
4
|
+
url: https://github.com/Ralioco/ralio-python/security/advisories/new
|
|
5
|
+
about: Report security issues privately — never in a public issue.
|
|
6
|
+
- name: Ralio documentation
|
|
7
|
+
url: https://docs.ralio.co
|
|
8
|
+
about: API reference, authentication guides, and concepts.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Suggest a new capability or improvement
|
|
3
|
+
labels: ["enhancement"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: What problem are you trying to solve?
|
|
9
|
+
description: Describe the use case, not just the proposed solution.
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: proposal
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposed solution
|
|
16
|
+
description: What would the API look like? A code sketch helps.
|
|
17
|
+
render: python
|
|
18
|
+
validations:
|
|
19
|
+
required: false
|
|
20
|
+
- type: textarea
|
|
21
|
+
id: alternatives
|
|
22
|
+
attributes:
|
|
23
|
+
label: Alternatives considered
|
|
24
|
+
validations:
|
|
25
|
+
required: false
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What does this change and why? -->
|
|
4
|
+
|
|
5
|
+
## Changes
|
|
6
|
+
|
|
7
|
+
<!-- Bullet the notable changes. -->
|
|
8
|
+
-
|
|
9
|
+
|
|
10
|
+
## Checklist
|
|
11
|
+
|
|
12
|
+
- [ ] `ruff check .` passes
|
|
13
|
+
- [ ] `mypy` passes
|
|
14
|
+
- [ ] `pytest -q` passes (new behavior has tests; network is mocked)
|
|
15
|
+
- [ ] `CHANGELOG.md` updated under the unreleased section
|
|
16
|
+
- [ ] No new runtime dependencies (or discussed in the issue)
|
|
17
|
+
- [ ] This PR touches security-sensitive code (key handling / signing / tokens) — flagged for extra review: yes / no
|
|
18
|
+
|
|
19
|
+
## Related issues
|
|
20
|
+
|
|
21
|
+
<!-- Closes #123 -->
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "pip"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
groups:
|
|
8
|
+
python-dependencies:
|
|
9
|
+
patterns:
|
|
10
|
+
- "*"
|
|
11
|
+
open-pull-requests-limit: 5
|
|
12
|
+
|
|
13
|
+
- package-ecosystem: "github-actions"
|
|
14
|
+
directory: "/"
|
|
15
|
+
schedule:
|
|
16
|
+
interval: "weekly"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v6
|
|
17
|
+
- uses: actions/setup-python@v6
|
|
18
|
+
with:
|
|
19
|
+
python-version: ${{ matrix.python-version }}
|
|
20
|
+
- run: python -m pip install --upgrade pip
|
|
21
|
+
- run: pip install -e ".[dev]"
|
|
22
|
+
- run: ruff check .
|
|
23
|
+
- run: mypy
|
|
24
|
+
- run: pytest -q
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Publishes to PyPI via Trusted Publishing (OIDC) when a version tag is pushed.
|
|
4
|
+
# No API token is stored — PyPI verifies the workflow identity directly.
|
|
5
|
+
# One-time setup: add this repo + workflow as a trusted publisher for the
|
|
6
|
+
# `ralio` project at https://pypi.org/manage/account/publishing/.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
tags:
|
|
11
|
+
- "v*"
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
build:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v6
|
|
21
|
+
- uses: actions/setup-python@v6
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
- run: python -m pip install --upgrade pip build twine
|
|
25
|
+
- run: python -m build
|
|
26
|
+
- run: twine check dist/*
|
|
27
|
+
- uses: actions/upload-artifact@v7
|
|
28
|
+
with:
|
|
29
|
+
name: dist
|
|
30
|
+
path: dist/
|
|
31
|
+
|
|
32
|
+
publish:
|
|
33
|
+
needs: build
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
environment: pypi
|
|
36
|
+
permissions:
|
|
37
|
+
id-token: write # required for Trusted Publishing
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/download-artifact@v8
|
|
40
|
+
with:
|
|
41
|
+
name: dist
|
|
42
|
+
path: dist/
|
|
43
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
ralio-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
.venv/
|
|
9
|
+
venv/
|
|
10
|
+
|
|
11
|
+
# Tooling
|
|
12
|
+
.mypy_cache/
|
|
13
|
+
.ruff_cache/
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
.coverage
|
|
16
|
+
htmlcov/
|
|
17
|
+
|
|
18
|
+
# Secrets — never commit private keys
|
|
19
|
+
*.pem
|
|
20
|
+
ralio-key*
|
|
21
|
+
|
|
22
|
+
# OS / editor
|
|
23
|
+
.DS_Store
|
|
24
|
+
.idea/
|
|
25
|
+
.vscode/
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.6.9
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff
|
|
6
|
+
args: [--fix]
|
|
7
|
+
- id: ruff-format
|
|
8
|
+
|
|
9
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
10
|
+
rev: v5.0.0
|
|
11
|
+
hooks:
|
|
12
|
+
- id: end-of-file-fixer
|
|
13
|
+
- id: trailing-whitespace
|
|
14
|
+
- id: check-yaml
|
|
15
|
+
- id: check-added-large-files
|
|
16
|
+
- id: detect-private-key
|
ralio-0.1.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 (unreleased)
|
|
4
|
+
|
|
5
|
+
Initial release.
|
|
6
|
+
|
|
7
|
+
- OAuth 2.1 `client_credentials` + `private_key_jwt` + DPoP authentication.
|
|
8
|
+
- One-time credential-binding registration (`ralio.register`) with
|
|
9
|
+
**synchronous activation** (server PR agentic-payment-gateway#1182): the
|
|
10
|
+
binding is active as soon as the submit call returns — no owner-approval
|
|
11
|
+
step, no polling. Ticket errors (`invalid_ticket`, `ticket_expired`,
|
|
12
|
+
`ticket_already_consumed` with `used_at`/`used_by_host` context,
|
|
13
|
+
`public_key_already_in_use`, `invalid_public_key`, `invalid_scope`,
|
|
14
|
+
`scope_exceeds_ticket_ceiling`) map into `RalioRegistrationError`.
|
|
15
|
+
- Zero-config onboarding, in lockstep with the Node SDK
|
|
16
|
+
(Ralioco/ralio-node#15): `register()` defaults its ticket to
|
|
17
|
+
`RALIO_REGISTRATION_TICKET`, mints the first access token, and persists
|
|
18
|
+
credentials to `~/.ralio/` (the CLI's store, so `register()` and
|
|
19
|
+
`ralio auth agent` are interchangeable; private key at
|
|
20
|
+
`~/.ralio/keys/<jkt>.pem`, `private_key_path` overrides). `RalioClient()`
|
|
21
|
+
then constructs with no arguments. Env overrides: `RALIO_API_URL`,
|
|
22
|
+
`RALIO_CONFIG_DIR`. `CredentialBinding` gained `key_path`; `scopes` now
|
|
23
|
+
reflects the granted token scope.
|
|
24
|
+
- `client.chat.send` and `client.chat.stream` (SSE). `agent_id` is optional —
|
|
25
|
+
when omitted, the SDK resolves the single agent the credential is bound to
|
|
26
|
+
(via `client.agents.list()`) and caches it.
|
|
27
|
+
- `client.agents.list` and the `Agent` type.
|
|
28
|
+
- `client.transactions.list` and `client.payment_intents.list` (paginated).
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
|
10
|
+
orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment:
|
|
18
|
+
|
|
19
|
+
- Demonstrating empathy and kindness toward other people
|
|
20
|
+
- Being respectful of differing opinions, viewpoints, and experiences
|
|
21
|
+
- Giving and gracefully accepting constructive feedback
|
|
22
|
+
- Accepting responsibility and apologizing to those affected by our mistakes
|
|
23
|
+
- Focusing on what is best for the overall community
|
|
24
|
+
|
|
25
|
+
Examples of unacceptable behavior:
|
|
26
|
+
|
|
27
|
+
- The use of sexualized language or imagery, and sexual attention or advances
|
|
28
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks
|
|
29
|
+
- Public or private harassment
|
|
30
|
+
- Publishing others' private information without their explicit permission
|
|
31
|
+
- Other conduct which could reasonably be considered inappropriate in a
|
|
32
|
+
professional setting
|
|
33
|
+
|
|
34
|
+
## Enforcement
|
|
35
|
+
|
|
36
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
37
|
+
reported to the maintainers at **conduct@ralio.co**. All complaints will be
|
|
38
|
+
reviewed and investigated promptly and fairly.
|
|
39
|
+
|
|
40
|
+
## Attribution
|
|
41
|
+
|
|
42
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
43
|
+
version 2.1, available at
|
|
44
|
+
https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
|
|
45
|
+
|
|
46
|
+
[homepage]: https://www.contributor-covenant.org
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in improving the Ralio Python SDK.
|
|
4
|
+
|
|
5
|
+
## Development setup
|
|
6
|
+
|
|
7
|
+
Requires Python 3.10+.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
git clone https://github.com/Ralioco/ralio-python
|
|
11
|
+
cd ralio-python
|
|
12
|
+
python -m venv .venv && source .venv/bin/activate
|
|
13
|
+
pip install -e ".[dev]"
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Checks
|
|
17
|
+
|
|
18
|
+
All of these must pass before a PR is merged; CI runs them on Python 3.10–3.13.
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
ruff check . # lint
|
|
22
|
+
mypy # static types (strict)
|
|
23
|
+
pytest -q # tests
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Optionally install the pre-commit hooks so the lint/type checks run on every
|
|
27
|
+
commit:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install pre-commit && pre-commit install
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Guidelines
|
|
34
|
+
|
|
35
|
+
- **Public API.** Anything importable from `ralio` (not underscore-prefixed) is
|
|
36
|
+
public and follows SemVer. Modules like `ralio._crypto` are internal and may
|
|
37
|
+
change without notice.
|
|
38
|
+
- **Types.** Every public function, method, and attribute is type-annotated;
|
|
39
|
+
`mypy --strict` must pass.
|
|
40
|
+
- **Tests.** New behavior needs tests. Network is mocked with `respx` — tests
|
|
41
|
+
must not hit a live API. Crypto correctness (DPoP/assertion claims and
|
|
42
|
+
signatures) is tested with real keys.
|
|
43
|
+
- **No new runtime dependencies** without discussion. The SDK intentionally
|
|
44
|
+
depends only on `httpx` and `PyJWT[crypto]`.
|
|
45
|
+
- **Security-sensitive code** (key handling, signing, token lifecycle) gets
|
|
46
|
+
extra review. If your change touches it, call that out in the PR.
|
|
47
|
+
|
|
48
|
+
## Commit messages & PRs
|
|
49
|
+
|
|
50
|
+
- Write a clear subject line in the imperative mood.
|
|
51
|
+
- Keep PRs focused; update `CHANGELOG.md` under the unreleased section.
|
|
52
|
+
- Link any related issue.
|
|
53
|
+
|
|
54
|
+
## Reporting bugs / requesting features
|
|
55
|
+
|
|
56
|
+
Use the issue templates. For security issues, see [SECURITY.md](SECURITY.md) —
|
|
57
|
+
do not file a public issue.
|
ralio-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ralio
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
ralio-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ralio
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official Python SDK for the Ralio agentic payment API.
|
|
5
|
+
Project-URL: Homepage, https://ralio.co
|
|
6
|
+
Project-URL: Documentation, https://docs.ralio.co
|
|
7
|
+
Author: Ralio
|
|
8
|
+
License: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: agents,dpop,oauth,payments,ralio,sdk
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: httpx>=0.27
|
|
22
|
+
Requires-Dist: pyjwt[crypto]>=2.8
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: respx>=0.21; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# Ralio Python SDK
|
|
31
|
+
|
|
32
|
+
[](https://pypi.org/project/ralio/)
|
|
33
|
+
[](https://pypi.org/project/ralio/)
|
|
34
|
+
[](https://github.com/Ralioco/ralio-python/actions/workflows/ci.yml)
|
|
35
|
+
[](LICENSE)
|
|
36
|
+
[](https://github.com/astral-sh/ruff)
|
|
37
|
+
|
|
38
|
+
The official Python client for the [Ralio](https://ralio.co) agentic payment API.
|
|
39
|
+
|
|
40
|
+
It handles the machine-authentication path end to end — OAuth 2.1
|
|
41
|
+
`client_credentials` with `private_key_jwt` and DPoP-bound access tokens — so
|
|
42
|
+
your integration can talk to an agent without hand-rolling JWT signing, proof
|
|
43
|
+
generation, or token refresh.
|
|
44
|
+
|
|
45
|
+
> **Scope.** This SDK targets autonomous integrations (CI jobs, agent hosts,
|
|
46
|
+
> server-side callers). It authenticates as a **credential binding**, which can
|
|
47
|
+
> hold the `agents:execute` and `transactions:read` scopes. Agent and binding
|
|
48
|
+
> management (`agents:config`) is a human-only operation in the console and is
|
|
49
|
+
> intentionally not part of this SDK.
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install ralio
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Requires Python 3.10+.
|
|
58
|
+
|
|
59
|
+
## Authentication model
|
|
60
|
+
|
|
61
|
+
Ralio's machine path has no shared secrets. Each credential is a P-256 private
|
|
62
|
+
key that lives on exactly one host:
|
|
63
|
+
|
|
64
|
+
1. The **owner** mints a one-time registration ticket in the console
|
|
65
|
+
(**Settings → Credentials → New credential**), choosing the target agent and
|
|
66
|
+
a scope ceiling. That is where consent happens. They send you the
|
|
67
|
+
`ralio-reg-…` ticket.
|
|
68
|
+
2. You call `ralio.register()` once on the agent host. It generates a keypair
|
|
69
|
+
locally and submits the public key with the ticket; the binding is active
|
|
70
|
+
as soon as the server responds — no approval step, no polling. The owner
|
|
71
|
+
gets an email receipt with a revoke link. The credentials are persisted to
|
|
72
|
+
`~/.ralio/` — the same store the `ralio` CLI uses, so `register()` and
|
|
73
|
+
`ralio auth agent` are interchangeable.
|
|
74
|
+
3. From then on, `RalioClient` mints and refreshes DPoP-bound access tokens
|
|
75
|
+
transparently and signs a fresh proof for every request.
|
|
76
|
+
|
|
77
|
+
See the [API authentication guide](https://docs.ralio.co/api-reference/authentication)
|
|
78
|
+
for the protocol details.
|
|
79
|
+
|
|
80
|
+
## Quickstart
|
|
81
|
+
|
|
82
|
+
With the owner's ticket in `RALIO_REGISTRATION_TICKET`, onboarding is two
|
|
83
|
+
calls:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
import ralio
|
|
87
|
+
|
|
88
|
+
ralio.register() # run once; the binding is active when this returns
|
|
89
|
+
|
|
90
|
+
client = ralio.RalioClient() # zero-config: reads the persisted credentials
|
|
91
|
+
reply = client.chat.send(message="What is my current balance?")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`register()` activates the binding in a single call (or raises
|
|
95
|
+
`RalioRegistrationError` if the ticket is invalid, expired, or already
|
|
96
|
+
consumed). The private key is generated locally, written to
|
|
97
|
+
`~/.ralio/keys/<jkt>.pem`, and never leaves the host.
|
|
98
|
+
|
|
99
|
+
Everything is overridable when you want to manage credentials yourself:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
import ralio
|
|
103
|
+
|
|
104
|
+
binding = ralio.register(
|
|
105
|
+
ticket="ralio-reg-...", # instead of RALIO_REGISTRATION_TICKET
|
|
106
|
+
private_key_path="ralio-key.pem", # generated and written here
|
|
107
|
+
requested_scopes=["agents:execute", "transactions:read"],
|
|
108
|
+
)
|
|
109
|
+
print(binding.client_id) # cb_... — store this alongside the key
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Use the client
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
import ralio
|
|
116
|
+
|
|
117
|
+
# Zero-config: reads the credentials persisted by register() / `ralio auth agent`.
|
|
118
|
+
client = ralio.RalioClient()
|
|
119
|
+
|
|
120
|
+
# Or manage credentials yourself:
|
|
121
|
+
# client = ralio.RalioClient(
|
|
122
|
+
# client_id="cb_...",
|
|
123
|
+
# private_key_path="ralio-key.pem",
|
|
124
|
+
# )
|
|
125
|
+
|
|
126
|
+
# Synchronous chat — agent_id is resolved automatically for a single-agent
|
|
127
|
+
# credential; pass agent_id explicitly to target one of several agents.
|
|
128
|
+
reply = client.chat.send(message="What is my current balance?")
|
|
129
|
+
print(reply.reply)
|
|
130
|
+
|
|
131
|
+
# Streaming chat (server-sent events)
|
|
132
|
+
for event in client.chat.stream(message="List my recent payments"):
|
|
133
|
+
if event.event == "text_delta":
|
|
134
|
+
print(event.text, end="", flush=True)
|
|
135
|
+
elif event.event == "tool_started":
|
|
136
|
+
print(f"\n[tool] {event.data['tool_name']}")
|
|
137
|
+
|
|
138
|
+
# Transactions — list endpoints are paginated; a Page is iterable and sized.
|
|
139
|
+
page = client.transactions.list(per_page=20)
|
|
140
|
+
print(f"showing {len(page)} of {page.total} transactions (page {page.page})")
|
|
141
|
+
for txn in page:
|
|
142
|
+
print(txn.date, txn.amount, txn.currency, txn.creditor, txn.status)
|
|
143
|
+
|
|
144
|
+
# Payment intents — what the agent proposed, with per-leg execution detail.
|
|
145
|
+
for intent in client.payment_intents.list(per_page=20):
|
|
146
|
+
print(intent.created_at, intent.total_amount, intent.currency, intent.approval_status)
|
|
147
|
+
|
|
148
|
+
client.close()
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
`RalioClient` is also a context manager:
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
with ralio.RalioClient() as client:
|
|
155
|
+
...
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Environment variables
|
|
159
|
+
|
|
160
|
+
| Variable | Meaning |
|
|
161
|
+
| --------------------------- | -------------------------------------------------------------------- |
|
|
162
|
+
| `RALIO_REGISTRATION_TICKET` | Default ticket for `register()` — same variable the CLI reads |
|
|
163
|
+
| `RALIO_API_URL` | API origin (default `https://api.ralio.co`) |
|
|
164
|
+
| `RALIO_CONFIG_DIR` | Credential store location (default `~/.ralio`, shared with the CLI) |
|
|
165
|
+
|
|
166
|
+
## Payments
|
|
167
|
+
|
|
168
|
+
There is no `payments.create()` method by design. Payments are executed by the
|
|
169
|
+
**agent**, not by direct REST calls: drive the agent with `chat.send` /
|
|
170
|
+
`chat.stream` ("Pay £500 to Bob for the April invoice") and it will create the
|
|
171
|
+
payment, subject to its spend limits and approval rules. Use
|
|
172
|
+
`transactions.list` (executed payments) and `payment_intents.list` (what the
|
|
173
|
+
agent proposed, with per-leg status) to read what the agent did.
|
|
174
|
+
|
|
175
|
+
## Errors
|
|
176
|
+
|
|
177
|
+
All errors subclass `ralio.RalioError`:
|
|
178
|
+
|
|
179
|
+
| Exception | When |
|
|
180
|
+
|-----------|------|
|
|
181
|
+
| `RalioAuthError` (401) | Missing/invalid token, failed assertion, or rejected DPoP proof |
|
|
182
|
+
| `RalioPermissionError` (403) | Token lacks the required scope, or resource not owned |
|
|
183
|
+
| `RalioNotFoundError` (404) | Resource doesn't exist |
|
|
184
|
+
| `RalioValidationError` (422) | Invalid field values or business-rule violation |
|
|
185
|
+
| `RalioRateLimitError` (429) | Rate limited — back off and retry |
|
|
186
|
+
| `RalioAPIError` | Any other HTTP error (carries `status_code`, `detail`) |
|
|
187
|
+
| `RalioRegistrationError` | Registration failed (invalid / expired / consumed ticket) |
|
|
188
|
+
| `RalioConfigError` | Local configuration problem |
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
import ralio
|
|
192
|
+
|
|
193
|
+
try:
|
|
194
|
+
client.chat.send(agent_id="...", message="...")
|
|
195
|
+
except ralio.RalioPermissionError as exc:
|
|
196
|
+
print("scope problem:", exc.detail)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Development
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
pip install -e ".[dev]"
|
|
203
|
+
ruff check .
|
|
204
|
+
mypy
|
|
205
|
+
pytest -q
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## License
|
|
209
|
+
|
|
210
|
+
MIT — see [LICENSE](LICENSE).
|