agentraas 0.2.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.
- agentraas-0.2.0/LICENSE +21 -0
- agentraas-0.2.0/PKG-INFO +133 -0
- agentraas-0.2.0/README.md +85 -0
- agentraas-0.2.0/agentraas/__init__.py +198 -0
- agentraas-0.2.0/agentraas.egg-info/PKG-INFO +133 -0
- agentraas-0.2.0/agentraas.egg-info/SOURCES.txt +9 -0
- agentraas-0.2.0/agentraas.egg-info/dependency_links.txt +1 -0
- agentraas-0.2.0/agentraas.egg-info/requires.txt +1 -0
- agentraas-0.2.0/agentraas.egg-info/top_level.txt +1 -0
- agentraas-0.2.0/pyproject.toml +35 -0
- agentraas-0.2.0/setup.cfg +4 -0
agentraas-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sumedh Chatse
|
|
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.
|
agentraas-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentraas
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Exactly-once execution for AI agents — Python SDK for AgentRaaS
|
|
5
|
+
Author: Sumedh Chatse
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Sumedh Chatse
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/sumedhchatse/agentraas
|
|
29
|
+
Project-URL: Repository, https://github.com/sumedhchatse/agentraas
|
|
30
|
+
Project-URL: Documentation, https://github.com/sumedhchatse/agentraas#readme
|
|
31
|
+
Project-URL: Issues, https://github.com/sumedhchatse/agentraas/issues
|
|
32
|
+
Keywords: ai-agents,idempotency,mcp,webhooks,n8n,reliability
|
|
33
|
+
Classifier: Development Status :: 4 - Beta
|
|
34
|
+
Classifier: Intended Audience :: Developers
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Programming Language :: Python :: 3
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
42
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
43
|
+
Requires-Python: >=3.8
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
License-File: LICENSE
|
|
46
|
+
Requires-Dist: requests>=2.28.0
|
|
47
|
+
Dynamic: license-file
|
|
48
|
+
|
|
49
|
+
# agentraas (Python SDK)
|
|
50
|
+
|
|
51
|
+
Exactly-once execution for AI agents — a thin, dependency-light wrapper
|
|
52
|
+
around [AgentRaaS](https://github.com/sumedhchatse/agentraas)'s SDK-style
|
|
53
|
+
REST gateway. If your agent code calls Stripe, Twilio, HubSpot, or any
|
|
54
|
+
other API directly, wrap it with this client so a retry — yours, your
|
|
55
|
+
framework's, or a flaky network — never becomes a duplicate charge, a
|
|
56
|
+
duplicate contact, or a duplicate message.
|
|
57
|
+
|
|
58
|
+
Works against any AgentRaaS deployment: self-hosted (`./install.sh`,
|
|
59
|
+
free and unlimited on every tier) or AgentRaaS Cloud.
|
|
60
|
+
|
|
61
|
+
## Install
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install agentraas
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Quickstart
|
|
68
|
+
|
|
69
|
+
1. Connect an agent from your AgentRaaS dashboard (**+ Connect Agent**) —
|
|
70
|
+
this gives you an `agentraas_key`, plus your `org_id` and `agent_id`.
|
|
71
|
+
2. Add credentials for the service you're calling (**Credentials** panel)
|
|
72
|
+
— AgentRaaS forwards to the real API using those, you never pass a
|
|
73
|
+
raw upstream API key through this SDK.
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import agentraas
|
|
77
|
+
|
|
78
|
+
client = agentraas.Client(
|
|
79
|
+
agentraas_key="ar_live_...",
|
|
80
|
+
org_id="acme-corp",
|
|
81
|
+
agent_id="billing-bot",
|
|
82
|
+
base_url="http://localhost:13000", # or your Cloud/self-hosted URL
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
result = client.call("stripe", "charge.create", {"amount": 5000, "currency": "usd"})
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Or with dot-notation sugar:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
stripe = client.service("stripe")
|
|
92
|
+
result = stripe.charge.create({"amount": 5000, "currency": "usd"})
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Calling a [Custom Action](https://github.com/sumedhchatse/agentraas#supported-services)
|
|
96
|
+
you've registered:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
result = client.custom("my-internal-webhook", {"foo": "bar"})
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Why `org_id` / `agent_id` matter
|
|
103
|
+
|
|
104
|
+
Omit them and every untagged SDK caller shares one unenforced identity
|
|
105
|
+
server-side — your per-agent rate limit and audit trail won't tell your
|
|
106
|
+
traffic apart from anyone else's. Set them once you've connected an
|
|
107
|
+
agent from the dashboard; it takes two extra kwargs.
|
|
108
|
+
|
|
109
|
+
## Retries are safe
|
|
110
|
+
|
|
111
|
+
AgentRaaS claims an atomic dedup slot server-side *before* forwarding
|
|
112
|
+
anything. If `client.call(...)` raises because of a timeout or a dropped
|
|
113
|
+
connection, calling it again with the same payload is safe — it either
|
|
114
|
+
completes normally or returns the cached result from the call that
|
|
115
|
+
actually went through. This SDK doesn't retry automatically; your own
|
|
116
|
+
retry logic (or your agent framework's) can be as aggressive as you want.
|
|
117
|
+
|
|
118
|
+
## Error handling
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from agentraas import AgentRaaSError
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
client.call("stripe", "charge.create", {"amount": 5000, "currency": "usd"})
|
|
125
|
+
except AgentRaaSError as err:
|
|
126
|
+
print(err.status_code, err.req_id, str(err))
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
MIT — see [LICENSE](./LICENSE). (The AgentRaaS server itself is
|
|
132
|
+
open-core; see the [main repo](https://github.com/sumedhchatse/agentraas)
|
|
133
|
+
for its licensing.)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# agentraas (Python SDK)
|
|
2
|
+
|
|
3
|
+
Exactly-once execution for AI agents — a thin, dependency-light wrapper
|
|
4
|
+
around [AgentRaaS](https://github.com/sumedhchatse/agentraas)'s SDK-style
|
|
5
|
+
REST gateway. If your agent code calls Stripe, Twilio, HubSpot, or any
|
|
6
|
+
other API directly, wrap it with this client so a retry — yours, your
|
|
7
|
+
framework's, or a flaky network — never becomes a duplicate charge, a
|
|
8
|
+
duplicate contact, or a duplicate message.
|
|
9
|
+
|
|
10
|
+
Works against any AgentRaaS deployment: self-hosted (`./install.sh`,
|
|
11
|
+
free and unlimited on every tier) or AgentRaaS Cloud.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install agentraas
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quickstart
|
|
20
|
+
|
|
21
|
+
1. Connect an agent from your AgentRaaS dashboard (**+ Connect Agent**) —
|
|
22
|
+
this gives you an `agentraas_key`, plus your `org_id` and `agent_id`.
|
|
23
|
+
2. Add credentials for the service you're calling (**Credentials** panel)
|
|
24
|
+
— AgentRaaS forwards to the real API using those, you never pass a
|
|
25
|
+
raw upstream API key through this SDK.
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
import agentraas
|
|
29
|
+
|
|
30
|
+
client = agentraas.Client(
|
|
31
|
+
agentraas_key="ar_live_...",
|
|
32
|
+
org_id="acme-corp",
|
|
33
|
+
agent_id="billing-bot",
|
|
34
|
+
base_url="http://localhost:13000", # or your Cloud/self-hosted URL
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
result = client.call("stripe", "charge.create", {"amount": 5000, "currency": "usd"})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Or with dot-notation sugar:
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
stripe = client.service("stripe")
|
|
44
|
+
result = stripe.charge.create({"amount": 5000, "currency": "usd"})
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Calling a [Custom Action](https://github.com/sumedhchatse/agentraas#supported-services)
|
|
48
|
+
you've registered:
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
result = client.custom("my-internal-webhook", {"foo": "bar"})
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Why `org_id` / `agent_id` matter
|
|
55
|
+
|
|
56
|
+
Omit them and every untagged SDK caller shares one unenforced identity
|
|
57
|
+
server-side — your per-agent rate limit and audit trail won't tell your
|
|
58
|
+
traffic apart from anyone else's. Set them once you've connected an
|
|
59
|
+
agent from the dashboard; it takes two extra kwargs.
|
|
60
|
+
|
|
61
|
+
## Retries are safe
|
|
62
|
+
|
|
63
|
+
AgentRaaS claims an atomic dedup slot server-side *before* forwarding
|
|
64
|
+
anything. If `client.call(...)` raises because of a timeout or a dropped
|
|
65
|
+
connection, calling it again with the same payload is safe — it either
|
|
66
|
+
completes normally or returns the cached result from the call that
|
|
67
|
+
actually went through. This SDK doesn't retry automatically; your own
|
|
68
|
+
retry logic (or your agent framework's) can be as aggressive as you want.
|
|
69
|
+
|
|
70
|
+
## Error handling
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from agentraas import AgentRaaSError
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
client.call("stripe", "charge.create", {"amount": 5000, "currency": "usd"})
|
|
77
|
+
except AgentRaaSError as err:
|
|
78
|
+
print(err.status_code, err.req_id, str(err))
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## License
|
|
82
|
+
|
|
83
|
+
MIT — see [LICENSE](./LICENSE). (The AgentRaaS server itself is
|
|
84
|
+
open-core; see the [main repo](https://github.com/sumedhchatse/agentraas)
|
|
85
|
+
for its licensing.)
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AgentRaaS Python SDK
|
|
3
|
+
Exactly-once execution for AI agents — a thin wrapper around the
|
|
4
|
+
AgentRaaS SDK-style REST gateway (POST /v1/sdk/:service/:action).
|
|
5
|
+
|
|
6
|
+
Quickstart:
|
|
7
|
+
import agentraas
|
|
8
|
+
|
|
9
|
+
client = agentraas.Client(
|
|
10
|
+
agentraas_key="ar_live_...", # from the dashboard's Connect Agent panel
|
|
11
|
+
org_id="acme-corp", # optional, but strongly recommended (see below)
|
|
12
|
+
agent_id="billing-bot", # optional, but strongly recommended (see below)
|
|
13
|
+
)
|
|
14
|
+
result = client.call("stripe", "charge.create", {"amount": 5000, "currency": "usd"})
|
|
15
|
+
|
|
16
|
+
# or, per-service sugar:
|
|
17
|
+
stripe = client.service("stripe")
|
|
18
|
+
result = stripe.charge.create({"amount": 5000, "currency": "usd"})
|
|
19
|
+
|
|
20
|
+
Why org_id/agent_id matter: without them, every SDK caller that omits
|
|
21
|
+
them shares one unenforced "sdk"/"sdk-agent" identity server-side — your
|
|
22
|
+
per-agent rate limit and audit trail won't distinguish your agents from
|
|
23
|
+
anyone else's untagged SDK traffic. Always set them once you've
|
|
24
|
+
connected an agent from the dashboard.
|
|
25
|
+
|
|
26
|
+
Retries are safe: AgentRaaS claims an atomic dedup slot server-side
|
|
27
|
+
before forwarding anything, so retrying a `call()` after a network
|
|
28
|
+
error (timeout, connection drop) never double-executes the real
|
|
29
|
+
action — the retry either completes normally or gets the cached
|
|
30
|
+
result back. This client does not retry automatically; your own
|
|
31
|
+
retry logic (or your agent framework's) is safe to use as-is.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
import requests
|
|
35
|
+
|
|
36
|
+
__version__ = "0.2.0"
|
|
37
|
+
|
|
38
|
+
DEFAULT_BASE_URL = "http://localhost:13000"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class AgentRaaSError(Exception):
|
|
42
|
+
"""Raised for any non-2xx response from AgentRaaS itself."""
|
|
43
|
+
|
|
44
|
+
def __init__(self, message, status_code=None, req_id=None):
|
|
45
|
+
super().__init__(message)
|
|
46
|
+
self.status_code = status_code
|
|
47
|
+
self.req_id = req_id
|
|
48
|
+
|
|
49
|
+
def __str__(self):
|
|
50
|
+
base = super().__str__()
|
|
51
|
+
if self.status_code:
|
|
52
|
+
base = f"[{self.status_code}] {base}"
|
|
53
|
+
if self.req_id:
|
|
54
|
+
base = f"{base} (reqId={self.req_id})"
|
|
55
|
+
return base
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class _ServiceProxy:
|
|
59
|
+
"""Returned by Client.service(name) — lets you write stripe.charge.create(...)
|
|
60
|
+
instead of client.call('stripe', 'charge.create', ...)."""
|
|
61
|
+
|
|
62
|
+
def __init__(self, client, service):
|
|
63
|
+
self._client = client
|
|
64
|
+
self._service = service
|
|
65
|
+
|
|
66
|
+
def __getattr__(self, prefix):
|
|
67
|
+
return _ActionProxy(self._client, self._service, prefix)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class _ActionProxy:
|
|
71
|
+
def __init__(self, client, service, prefix):
|
|
72
|
+
self._client = client
|
|
73
|
+
self._service = service
|
|
74
|
+
self._prefix = prefix
|
|
75
|
+
|
|
76
|
+
def __getattr__(self, suffix):
|
|
77
|
+
action = f"{self._prefix}.{suffix}"
|
|
78
|
+
return lambda payload=None: self._client.call(self._service, action, payload)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class Client:
|
|
82
|
+
"""A reusable AgentRaaS client. One Client per agent identity — create
|
|
83
|
+
it once and reuse it for every call, rather than per-request."""
|
|
84
|
+
|
|
85
|
+
def __init__(self, agentraas_key, org_id=None, agent_id=None, base_url=None, timeout=30):
|
|
86
|
+
"""
|
|
87
|
+
Args:
|
|
88
|
+
agentraas_key: Your AgentRaaS agent API key (ar_live_... — from
|
|
89
|
+
the dashboard's Connect Agent panel).
|
|
90
|
+
org_id: Your org id. Optional but recommended — see module docstring.
|
|
91
|
+
agent_id: Your agent id. Optional but recommended — see module docstring.
|
|
92
|
+
base_url: Your AgentRaaS deployment's base URL, e.g.
|
|
93
|
+
"https://your-deployment.example.com" or
|
|
94
|
+
"http://localhost:13000" for a local self-hosted instance
|
|
95
|
+
(the default). Cloud users: use your AgentRaaS Cloud URL.
|
|
96
|
+
timeout: Per-request timeout in seconds (default 30).
|
|
97
|
+
"""
|
|
98
|
+
if not agentraas_key:
|
|
99
|
+
raise ValueError("agentraas_key is required")
|
|
100
|
+
self.agentraas_key = agentraas_key
|
|
101
|
+
self.org_id = org_id
|
|
102
|
+
self.agent_id = agent_id
|
|
103
|
+
self.base_url = (base_url or DEFAULT_BASE_URL).rstrip("/")
|
|
104
|
+
self.timeout = timeout
|
|
105
|
+
self._session = requests.Session()
|
|
106
|
+
|
|
107
|
+
def _headers(self):
|
|
108
|
+
headers = {
|
|
109
|
+
"Content-Type": "application/json",
|
|
110
|
+
"X-AgentRaaS-Key": self.agentraas_key,
|
|
111
|
+
}
|
|
112
|
+
if self.org_id:
|
|
113
|
+
headers["X-AgentRaaS-Org"] = self.org_id
|
|
114
|
+
if self.agent_id:
|
|
115
|
+
headers["X-AgentRaaS-Agent"] = self.agent_id
|
|
116
|
+
return headers
|
|
117
|
+
|
|
118
|
+
def call(self, service, action, payload=None):
|
|
119
|
+
"""Make one protected request.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
service: Curated service name (stripe, twilio, hubspot, ...
|
|
123
|
+
see your dashboard's Services list) or "custom" for a
|
|
124
|
+
Custom Action you've registered.
|
|
125
|
+
action: Action name — for curated services, the dotted
|
|
126
|
+
action from that service's docs (e.g. "charge.create");
|
|
127
|
+
for service="custom", the Custom Action's registered name.
|
|
128
|
+
payload: Request body dict, forwarded to the upstream API.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
The upstream response body as a dict (or the cached result,
|
|
132
|
+
with "cached": true, if this exact request already ran).
|
|
133
|
+
|
|
134
|
+
Raises:
|
|
135
|
+
AgentRaaSError: on any non-2xx response.
|
|
136
|
+
"""
|
|
137
|
+
url = f"{self.base_url}/v1/sdk/{service}/{action}"
|
|
138
|
+
try:
|
|
139
|
+
response = self._session.post(
|
|
140
|
+
url, headers=self._headers(), json=payload or {}, timeout=self.timeout
|
|
141
|
+
)
|
|
142
|
+
except requests.RequestException as err:
|
|
143
|
+
raise AgentRaaSError(f"Could not reach AgentRaaS at {self.base_url}: {err}") from err
|
|
144
|
+
|
|
145
|
+
if response.status_code >= 400:
|
|
146
|
+
try:
|
|
147
|
+
error_data = response.json()
|
|
148
|
+
except ValueError:
|
|
149
|
+
error_data = {}
|
|
150
|
+
raise AgentRaaSError(
|
|
151
|
+
error_data.get("error", f"HTTP {response.status_code}"),
|
|
152
|
+
status_code=response.status_code,
|
|
153
|
+
req_id=error_data.get("reqId"),
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
return response.json()
|
|
157
|
+
|
|
158
|
+
def custom(self, action, payload=None):
|
|
159
|
+
"""Shorthand for call("custom", action, payload) — calls one of
|
|
160
|
+
your registered Custom Actions by name."""
|
|
161
|
+
return self.call("custom", action, payload)
|
|
162
|
+
|
|
163
|
+
def service(self, name):
|
|
164
|
+
"""Returns a proxy for dot-notation calls: client.service("stripe").charge.create(payload)."""
|
|
165
|
+
return _ServiceProxy(self, name)
|
|
166
|
+
|
|
167
|
+
def close(self):
|
|
168
|
+
self._session.close()
|
|
169
|
+
|
|
170
|
+
def __enter__(self):
|
|
171
|
+
return self
|
|
172
|
+
|
|
173
|
+
def __exit__(self, exc_type, exc, tb):
|
|
174
|
+
self.close()
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def protect(service, agentraas_key, org_id=None, agent_id=None, base_url=None):
|
|
178
|
+
"""Deprecated convenience shim for pre-0.2 callers. Prefer Client(...).service(name).
|
|
179
|
+
|
|
180
|
+
Usage:
|
|
181
|
+
import agentraas
|
|
182
|
+
stripe = agentraas.protect("stripe", agentraas_key="ar_live_...")
|
|
183
|
+
result = stripe.request("charge.create", {"amount": 5000, "currency": "usd"})
|
|
184
|
+
"""
|
|
185
|
+
client = Client(agentraas_key, org_id=org_id, agent_id=agent_id, base_url=base_url)
|
|
186
|
+
return _LegacyProxy(client, service)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class _LegacyProxy:
|
|
190
|
+
def __init__(self, client, service):
|
|
191
|
+
self._client = client
|
|
192
|
+
self._service = service
|
|
193
|
+
|
|
194
|
+
def request(self, action, payload=None):
|
|
195
|
+
return self._client.call(self._service, action, payload)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
__all__ = ["Client", "AgentRaaSError", "protect"]
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentraas
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Exactly-once execution for AI agents — Python SDK for AgentRaaS
|
|
5
|
+
Author: Sumedh Chatse
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Sumedh Chatse
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/sumedhchatse/agentraas
|
|
29
|
+
Project-URL: Repository, https://github.com/sumedhchatse/agentraas
|
|
30
|
+
Project-URL: Documentation, https://github.com/sumedhchatse/agentraas#readme
|
|
31
|
+
Project-URL: Issues, https://github.com/sumedhchatse/agentraas/issues
|
|
32
|
+
Keywords: ai-agents,idempotency,mcp,webhooks,n8n,reliability
|
|
33
|
+
Classifier: Development Status :: 4 - Beta
|
|
34
|
+
Classifier: Intended Audience :: Developers
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Programming Language :: Python :: 3
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
42
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
43
|
+
Requires-Python: >=3.8
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
License-File: LICENSE
|
|
46
|
+
Requires-Dist: requests>=2.28.0
|
|
47
|
+
Dynamic: license-file
|
|
48
|
+
|
|
49
|
+
# agentraas (Python SDK)
|
|
50
|
+
|
|
51
|
+
Exactly-once execution for AI agents — a thin, dependency-light wrapper
|
|
52
|
+
around [AgentRaaS](https://github.com/sumedhchatse/agentraas)'s SDK-style
|
|
53
|
+
REST gateway. If your agent code calls Stripe, Twilio, HubSpot, or any
|
|
54
|
+
other API directly, wrap it with this client so a retry — yours, your
|
|
55
|
+
framework's, or a flaky network — never becomes a duplicate charge, a
|
|
56
|
+
duplicate contact, or a duplicate message.
|
|
57
|
+
|
|
58
|
+
Works against any AgentRaaS deployment: self-hosted (`./install.sh`,
|
|
59
|
+
free and unlimited on every tier) or AgentRaaS Cloud.
|
|
60
|
+
|
|
61
|
+
## Install
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install agentraas
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Quickstart
|
|
68
|
+
|
|
69
|
+
1. Connect an agent from your AgentRaaS dashboard (**+ Connect Agent**) —
|
|
70
|
+
this gives you an `agentraas_key`, plus your `org_id` and `agent_id`.
|
|
71
|
+
2. Add credentials for the service you're calling (**Credentials** panel)
|
|
72
|
+
— AgentRaaS forwards to the real API using those, you never pass a
|
|
73
|
+
raw upstream API key through this SDK.
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import agentraas
|
|
77
|
+
|
|
78
|
+
client = agentraas.Client(
|
|
79
|
+
agentraas_key="ar_live_...",
|
|
80
|
+
org_id="acme-corp",
|
|
81
|
+
agent_id="billing-bot",
|
|
82
|
+
base_url="http://localhost:13000", # or your Cloud/self-hosted URL
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
result = client.call("stripe", "charge.create", {"amount": 5000, "currency": "usd"})
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Or with dot-notation sugar:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
stripe = client.service("stripe")
|
|
92
|
+
result = stripe.charge.create({"amount": 5000, "currency": "usd"})
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Calling a [Custom Action](https://github.com/sumedhchatse/agentraas#supported-services)
|
|
96
|
+
you've registered:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
result = client.custom("my-internal-webhook", {"foo": "bar"})
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Why `org_id` / `agent_id` matter
|
|
103
|
+
|
|
104
|
+
Omit them and every untagged SDK caller shares one unenforced identity
|
|
105
|
+
server-side — your per-agent rate limit and audit trail won't tell your
|
|
106
|
+
traffic apart from anyone else's. Set them once you've connected an
|
|
107
|
+
agent from the dashboard; it takes two extra kwargs.
|
|
108
|
+
|
|
109
|
+
## Retries are safe
|
|
110
|
+
|
|
111
|
+
AgentRaaS claims an atomic dedup slot server-side *before* forwarding
|
|
112
|
+
anything. If `client.call(...)` raises because of a timeout or a dropped
|
|
113
|
+
connection, calling it again with the same payload is safe — it either
|
|
114
|
+
completes normally or returns the cached result from the call that
|
|
115
|
+
actually went through. This SDK doesn't retry automatically; your own
|
|
116
|
+
retry logic (or your agent framework's) can be as aggressive as you want.
|
|
117
|
+
|
|
118
|
+
## Error handling
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from agentraas import AgentRaaSError
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
client.call("stripe", "charge.create", {"amount": 5000, "currency": "usd"})
|
|
125
|
+
except AgentRaaSError as err:
|
|
126
|
+
print(err.status_code, err.req_id, str(err))
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
MIT — see [LICENSE](./LICENSE). (The AgentRaaS server itself is
|
|
132
|
+
open-core; see the [main repo](https://github.com/sumedhchatse/agentraas)
|
|
133
|
+
for its licensing.)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests>=2.28.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
agentraas
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "agentraas"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Exactly-once execution for AI agents — Python SDK for AgentRaaS"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { file = "LICENSE" }
|
|
11
|
+
authors = [{ name = "Sumedh Chatse" }]
|
|
12
|
+
requires-python = ">=3.8"
|
|
13
|
+
dependencies = ["requests>=2.28.0"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.8",
|
|
20
|
+
"Programming Language :: Python :: 3.9",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
25
|
+
]
|
|
26
|
+
keywords = ["ai-agents", "idempotency", "mcp", "webhooks", "n8n", "reliability"]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://github.com/sumedhchatse/agentraas"
|
|
30
|
+
Repository = "https://github.com/sumedhchatse/agentraas"
|
|
31
|
+
Documentation = "https://github.com/sumedhchatse/agentraas#readme"
|
|
32
|
+
Issues = "https://github.com/sumedhchatse/agentraas/issues"
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.packages.find]
|
|
35
|
+
include = ["agentraas*"]
|