11# OnceOnly Python SDK — Examples
22
33This folder contains ** small, runnable examples** demonstrating how to use the OnceOnly Python SDK.
4+
45Examples are organized into two groups:
56
67- ` examples/general/ ` — core idempotency use cases (webhooks, workers, automations)
7- - ` examples/ai/ ` — AI agent and tool-calling integrations
8+ - ` examples/ai/ ` — AI agents, long-running jobs, and tool-calling integrations
89
910---
1011
1112## Prerequisites
1213
13- 1 ) Install the SDK (from repo root):
14+ 1 ) Install the SDK (from repository root):
1415
1516``` bash
1617pip install -e .
@@ -28,7 +29,7 @@ All examples read `ONCEONLY_API_KEY` from the environment.
2829
2930## Running examples
3031
31- From the repository root:
32+ Always run examples from the repository root:
3233
3334``` bash
3435python examples/general/basic_check_lock.py
@@ -42,7 +43,7 @@ python examples/general/basic_check_lock.py
4243Minimal idempotency primitive.
4344
4445- First call → ` locked=True `
45- - Second call with same key → ` duplicate=True `
46+ - Second call with the same key → ` duplicate=True `
4647
4748Use this pattern for:
4849- Webhooks
@@ -64,10 +65,10 @@ Demonstrates TTL behavior.
6465Attaches metadata to an idempotency key.
6566
6667Typical metadata:
67- - user_id
68- - scenario_id
69- - webhook_event_id
70- - trace_id
68+ - ` user_id `
69+ - ` scenario_id `
70+ - ` webhook_event_id `
71+ - ` trace_id `
7172
7273Metadata is useful for debugging and analytics.
7374If the server does not echo it back, the SDK preserves it in ` result.raw ` .
@@ -98,7 +99,7 @@ Designed for:
9899---
99100
100101### ` decorator_pydantic.py `
101- Advanced decorator example with ** Pydantic models** .
102+ Advanced decorator example using ** Pydantic models** .
102103
103104Highlights:
104105- Stable hashing for complex objects
@@ -113,7 +114,7 @@ This solves a common pain point for AI and API developers.
113114Inspect account and usage information.
114115
115116Endpoints used:
116- - ` /v1/me ` — API key & plan info
117+ - ` /v1/me ` — API key and plan info
117118- ` /v1/usage ` — current usage vs limits
118119
119120Useful for:
@@ -123,84 +124,92 @@ Useful for:
123124
124125---
125126
126- ## AI / Agent examples (` examples/ai/ ` )
127+ ## AI examples (` examples/ai/ ` )
127128
128- ### ` agent_guard_manual .py`
129- Manual guard pattern for AI agents .
129+ ### ` run_and_wait .py`
130+ Canonical long-running AI job example .
130131
131- - Call ` check_lock() ` before performing a tool action
132- - Abort immediately if duplicate
132+ - Uses ` /v1/ai/run `
133+ - Polls status until completion
134+ - Charged ** once per key** , polling is free
133135
134136Best for:
135- - Custom agent loops
136- - Tool routing
137- - Expensive API calls
137+ - Background AI jobs
138+ - Batch processing
139+ - Server-side agents
138140
139141---
140142
141- ### ` agent_retry_safe .py`
142- Agent restart / retry safety example .
143+ ### ` agent_action_local .py`
144+ Local side-effect guard using the AI Lease API .
143145
144- - Run the script once: performs the side-effect
145- - Run it again: duplicate is detected and the side-effect is skipped
146+ - Uses ` /v1/ai/lease `
147+ - Executes the side-effect locally
148+ - Ensures exactly-once execution across retries and crashes
146149
147- This is a core pattern for autonomous agents that can crash, retry, or resume.
150+ Best for:
151+ - Payments
152+ - Emails
153+ - Webhooks triggered by agents
148154
149155---
150156
151- ### ` langchain_tool .py`
152- LangChain integration example.
157+ ### ` poll_status .py`
158+ Polling example for AI jobs .
153159
154- - Wraps a standard LangChain ` Tool `
155- - Automatically enforces idempotency
156- - Prevents double execution of side-effects
160+ - Uses ` /v1/ai/status `
161+ - Demonstrates ` retry_after_sec ` and adaptive polling
157162
158- Optional dependency:
163+ ---
159164
160- ``` bash
161- pip install langchain-core
162- ```
165+ ### ` get_result.py `
166+ Fetches the final result of a completed AI job.
163167
164- Works well with:
165- - LangChain agents
166- - Tool-calling LLMs
167- - Multi-step plans
168+ - Uses ` /v1/ai/result `
169+ - Safe to call multiple times
168170
169171---
170172
171- ### ` long_running_job .py`
172- Long-running AI / backend job example .
173+ ### ` langchain_tool_ai_lease .py`
174+ LangChain integration example using the AI Lease API .
173175
174- - Uses OnceOnly AI client helpers
175- - Demonstrates run → poll → wait pattern
176- - Suitable for batch AI jobs or background processing
176+ - Wraps a LangChain tool
177+ - Guarantees exactly-once tool execution
178+ - Prevents double side-effects
179+ - Protects against LLM 'hallucinations' causing multiple tool calls
180+
181+ Optional dependency:
182+
183+ ``` bash
184+ pip install langchain-core
185+ ```
177186
178187---
179188
180189## Design tips
181190
182- - ** Key design:** Model keys after real-world actions
191+ - ** Key design:** model keys after real-world actions
183192 Example:
184193 ```
185194 agent:email:user42:welcome
186- make:scenario:123:event:evt_abc
195+ ai:job:daily_summary:2026-01-09
187196 ```
188197
189- - ** TTL:** Choose TTL based on how long a duplicate would be dangerous
198+ - ** TTL:** choose TTL based on how long a duplicate would be dangerous
190199
191- - ** Fail-open:**
192- - ` fail_open=True ` (default): safer for production workflows
200+ - ** Fail-open behavior :**
201+ - ` fail_open=True ` (default): safer for production workflows
193202 - ` fail_open=False ` : strict correctness for critical paths
194203
195204---
196205
197206## Troubleshooting
198207
199208- ** 401 / 403** — invalid or missing API key
200- - ** 402** — plan limit reached
201- - ** 429** — rate limit exceeded (backoff & retry )
209+ - ** 402** — plan or usage limit reached
210+ - ** 429** — rate limit exceeded (retry with backoff )
202211- ** 5xx** — server error (fail-open may apply)
203212
204213---
205214
206- If you need an additional example , open an issue or PR.
215+ If you need additional examples , open an issue or submit a PR.
0 commit comments