Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,6 @@ OpenGradient supports multiple settlement modes through the x402 payment protoco

- **PRIVATE**: Payment only, no input/output data on-chain (maximum privacy)
- **BATCH_HASHED**: Aggregates inferences into a Merkle tree with input/output hashes and signatures (most cost-efficient, default)
- **INDIVIDUAL_FULL**: Records input, output, timestamp, and verification on-chain (maximum auditability)

Specify settlement mode in your requests:
```python
Expand Down
5 changes: 2 additions & 3 deletions docs/CLAUDE_SDK_USERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,8 @@ og.InferenceMode.TEE # Trusted Execution Environment
og.InferenceMode.ZKML # Zero-knowledge proof

# x402 Payment Settlement Modes (for LLM calls)
og.x402SettlementMode.PRIVATE # Input/output hashes only (most private)
og.x402SettlementMode.BATCH_HASHED # Batch hashes (most cost-efficient, default)
og.x402SettlementMode.INDIVIDUAL_FULL # Full data and metadata on-chain
og.x402SettlementMode.PRIVATE # Payment only; inference data stays off-chain
og.x402SettlementMode.BATCH_HASHED # Batch hashes (most cost-efficient, default)

# Workflow data types
og.CandleType.OPEN, .HIGH, .LOW, .CLOSE, .VOLUME
Expand Down
14 changes: 5 additions & 9 deletions docs/opengradient/client/llm.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ Perform inference on an LLM model using chat via TEE.
* **`x402_settlement_mode (x402SettlementMode, optional)`**: Settlement mode for x402 payments.
- PRIVATE: Payment only, no input/output data on-chain (most privacy-preserving).
- BATCH_HASHED: Aggregates inferences into a Merkle tree with input/output hashes and signatures (default, most cost-efficient).
- INDIVIDUAL_FULL: Records input, output, timestamp, and verification on-chain (maximum auditability).
Defaults to BATCH_HASHED.
* **`stream (bool, optional)`**: Whether to stream the response. Default is False.

Expand All @@ -115,9 +114,8 @@ Union[TextGenerationOutput, AsyncGenerator[StreamChunk, None]]:
* **`data_settlement_transaction_hash`**: Blockchain transaction hash for
the data settlement transaction. ``None`` when the provider
does not return data settlement metadata.
* **`data_settlement_blob_id`**: Walrus blob ID for individual data
settlement. ``None`` for private/batch settlement or when the
provider does not return it.
* **`data_settlement_blob_id`**: Walrus blob ID for data settlement.
``None`` when the provider does not return it.
* **`finish_reason`**: Reason the model stopped generating
(e.g. ``"stop"``, ``"tool_call"``, ``"error"``).
Only populated for chat requests.
Expand Down Expand Up @@ -179,7 +177,6 @@ Perform inference on an LLM model using completions via TEE.
* **`x402_settlement_mode (x402SettlementMode, optional)`**: Settlement mode for x402 payments.
- PRIVATE: Payment only, no input/output data on-chain (most privacy-preserving).
- BATCH_HASHED: Aggregates inferences into a Merkle tree with input/output hashes and signatures (default, most cost-efficient).
- INDIVIDUAL_FULL: Records input, output, timestamp, and verification on-chain (maximum auditability).
Defaults to BATCH_HASHED.

**Returns**
Expand All @@ -194,9 +191,8 @@ TextGenerationOutput: Generated text results including:
* **`data_settlement_transaction_hash`**: Blockchain transaction hash for
the data settlement transaction. ``None`` when the provider
does not return data settlement metadata.
* **`data_settlement_blob_id`**: Walrus blob ID for individual data
settlement. ``None`` for private/batch settlement or when the
provider does not return it.
* **`data_settlement_blob_id`**: Walrus blob ID for data settlement.
``None`` when the provider does not return it.
* **`finish_reason`**: Reason the model stopped generating
(e.g. ``"stop"``, ``"tool_call"``, ``"error"``).
Only populated for chat requests.
Expand Down Expand Up @@ -269,4 +265,4 @@ Resolve the current TEE or a specific active registry TEE.

This is primarily for backend relays that need SDK-managed TEE routing,
TLS pinning, and x402 clients without using the chat/completion helpers
directly, for example when forwarding OHTTP ciphertext.
directly, for example when forwarding OHTTP ciphertext.
5 changes: 2 additions & 3 deletions docs/opengradient/client/twins.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,8 @@ TextGenerationOutput: Generated text results including chat_output and finish_re
* **`data_settlement_transaction_hash`**: Blockchain transaction hash for
the data settlement transaction. ``None`` when the provider
does not return data settlement metadata.
* **`data_settlement_blob_id`**: Walrus blob ID for individual data
settlement. ``None`` for private/batch settlement or when the
provider does not return it.
* **`data_settlement_blob_id`**: Walrus blob ID for data settlement.
``None`` when the provider does not return it.
* **`finish_reason`**: Reason the model stopped generating
(e.g. ``"stop"``, ``"tool_call"``, ``"error"``).
Only populated for chat requests.
Expand Down
16 changes: 5 additions & 11 deletions docs/opengradient/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ usage information.
* **`tee_payment_address`**: Payment address registered for the TEE (final chunk only)
* **`data_settlement_transaction_hash`**: Transaction hash for the data settlement
transaction, present on the final chunk when available.
* **`data_settlement_blob_id`**: Walrus blob ID for individual data settlement,
* **`data_settlement_blob_id`**: Walrus blob ID for data settlement,
present on the final chunk when available.
* **`images`**: Generated images returned by image-output models, present on the
final chunk when available. Each entry is a ``data:`` URI.
Expand Down Expand Up @@ -410,7 +410,7 @@ StreamChunk instance
* **`tee_payment_address`**: Payment address registered for the TEE (final chunk only)
* **`data_settlement_transaction_hash`**: Transaction hash for the data settlement
transaction, present on the final chunk when available.
* **`data_settlement_blob_id`**: Walrus blob ID for individual data settlement,
* **`data_settlement_blob_id`**: Walrus blob ID for data settlement,
present on the final chunk when available.
* **`images`**: Generated images returned by image-output models, present on the
final chunk when available. Each entry is a ``data:`` URI.
Expand Down Expand Up @@ -557,9 +557,8 @@ Trust model:
* **`data_settlement_transaction_hash`**: Blockchain transaction hash for
the data settlement transaction. ``None`` when the provider
does not return data settlement metadata.
* **`data_settlement_blob_id`**: Walrus blob ID for individual data
settlement. ``None`` for private/batch settlement or when the
provider does not return it.
* **`data_settlement_blob_id`**: Walrus blob ID for data settlement.
``None`` when the provider does not return it.
* **`finish_reason`**: Reason the model stopped generating
(e.g. ``"stop"``, ``"tool_call"``, ``"error"``).
Only populated for chat requests.
Expand Down Expand Up @@ -633,9 +632,4 @@ privacy, and transaction costs.
Aggregates multiple inferences into a single settlement transaction
using a Merkle tree containing input hashes, output hashes, and signatures.
Most cost-efficient for high-volume applications.
CLI usage: --settlement-mode batch-hashed
* **`INDIVIDUAL_FULL`**: Individual settlement with full metadata.
Records input data, output data, timestamp, and verification on-chain.
Provides maximum transparency and auditability.
Higher gas costs due to larger data storage.
CLI usage: --settlement-mode individual-full
CLI usage: --settlement-mode batch-hashed
2 changes: 1 addition & 1 deletion examples/langchain_react_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
private_key=private_key,
model_cid=og.TEE_LLM.GPT_4_1_2025_04_14,
max_tokens=300,
x402_settlement_mode=og.x402SettlementMode.INDIVIDUAL_FULL,
x402_settlement_mode=og.x402SettlementMode.BATCH_HASHED,
)


Expand Down
4 changes: 2 additions & 2 deletions examples/llm_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ async def main():
{"role": "user", "content": "What model are you?"},
]

# Run inference with full public settlement
# Run inference with batched settlement
result = await llm.chat(
model=og.TEE_LLM.CLAUDE_OPUS_4_8,
messages=messages,
max_tokens=300,
x402_settlement_mode=og.x402SettlementMode.INDIVIDUAL_FULL,
x402_settlement_mode=og.x402SettlementMode.BATCH_HASHED,
)
print(result.chat_output["content"])

Expand Down
11 changes: 5 additions & 6 deletions examples/llm_chat_streaming.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ async def main():
{"role": "user", "content": "What makes it good for beginners?"},
]

settlement_mode = og.x402SettlementMode.INDIVIDUAL_FULL
settlement_mode = og.x402SettlementMode.BATCH_HASHED
stream = await llm.chat(
model=og.TEE_LLM.GPT_4_1_2025_04_14,
messages=messages,
Expand All @@ -27,11 +27,10 @@ async def main():
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)

if settlement_mode == og.x402SettlementMode.INDIVIDUAL_FULL:
if chunk.data_settlement_blob_id:
print("\n Data Settlement Blob ID: ", chunk.data_settlement_blob_id)
if chunk.data_settlement_transaction_hash:
print("\n Data Settlement Transaction Hash: ", chunk.data_settlement_transaction_hash)
if chunk.data_settlement_blob_id:
print("\n Data Settlement Blob ID: ", chunk.data_settlement_blob_id)
if chunk.data_settlement_transaction_hash:
print("\n Data Settlement Transaction Hash: ", chunk.data_settlement_transaction_hash)


asyncio.run(main())
4 changes: 2 additions & 2 deletions integrationtest/llm/test_llm_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ async def test_chat(llm_client):
model=og.TEE_LLM.GEMINI_2_5_FLASH,
messages=messages,
max_tokens=50,
x402_settlement_mode=og.x402SettlementMode.INDIVIDUAL_FULL,
x402_settlement_mode=og.x402SettlementMode.BATCH_HASHED,
)

assert result is not None
Expand All @@ -152,7 +152,7 @@ async def test_chat_streaming(llm_client):
model=og.TEE_LLM.GEMINI_2_5_FLASH,
messages=messages,
max_tokens=50,
x402_settlement_mode=og.x402SettlementMode.INDIVIDUAL_FULL,
x402_settlement_mode=og.x402SettlementMode.BATCH_HASHED,
stream=True,
)

Expand Down
5 changes: 2 additions & 3 deletions src/opengradient/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ def convert(self, value, param, ctx):
x402SettlementModes = {
"batch-hashed": x402SettlementMode.BATCH_HASHED,
"private": x402SettlementMode.PRIVATE,
"individual-full": x402SettlementMode.INDIVIDUAL_FULL,
}


Expand Down Expand Up @@ -384,7 +383,7 @@ def infer(ctx, model_cid: str, inference_mode: str, input_data, input_file: Path
"x402_settlement_mode",
type=click.Choice(x402SettlementModes.keys()),
default="batch-hashed",
help="Settlement mode for x402 payments: private (payment only), batch-hashed (default), individual-full (full data with verification)",
help="Settlement mode for x402 payments: private (payment only), batch-hashed (default)",
)
@click.pass_context
def completion(
Expand Down Expand Up @@ -518,7 +517,7 @@ def print_llm_completion_result(model_cid, tx_hash, llm_output, is_vanilla=True,
"--x402-settlement-mode",
type=click.Choice(x402SettlementModes.keys()),
default="batch-hashed",
help="Settlement mode for x402 payments: private (payment only), batch-hashed (default), individual-full (full data with verification)",
help="Settlement mode for x402 payments: private (payment only), batch-hashed (default)",
)
@click.option("--stream", is_flag=True, default=False, help="Stream the output from the LLM")
@click.pass_context
Expand Down
2 changes: 0 additions & 2 deletions src/opengradient/client/llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,6 @@ async def completion(
x402_settlement_mode (x402SettlementMode, optional): Settlement mode for x402 payments.
- PRIVATE: Payment only, no input/output data on-chain (most privacy-preserving).
- BATCH_HASHED: Aggregates inferences into a Merkle tree with input/output hashes and signatures (default, most cost-efficient).
- INDIVIDUAL_FULL: Records input, output, timestamp, and verification on-chain (maximum auditability).
Defaults to BATCH_HASHED.

Returns:
Expand Down Expand Up @@ -427,7 +426,6 @@ async def chat(
x402_settlement_mode (x402SettlementMode, optional): Settlement mode for x402 payments.
- PRIVATE: Payment only, no input/output data on-chain (most privacy-preserving).
- BATCH_HASHED: Aggregates inferences into a Merkle tree with input/output hashes and signatures (default, most cost-efficient).
- INDIVIDUAL_FULL: Records input, output, timestamp, and verification on-chain (maximum auditability).
Defaults to BATCH_HASHED.
stream (bool, optional): Whether to stream the response. Default is False.

Expand Down
16 changes: 4 additions & 12 deletions src/opengradient/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ class x402SettlementMode(str, Enum):
Most cost-efficient for high-volume applications.
CLI usage: --settlement-mode batch-hashed

INDIVIDUAL_FULL: Individual settlement with full metadata.
Records input data, output data, timestamp, and verification on-chain.
Provides maximum transparency and auditability.
Higher gas costs due to larger data storage.
CLI usage: --settlement-mode individual-full

Examples:
>>> from opengradient import x402SettlementMode
>>> mode = x402SettlementMode.PRIVATE
Expand All @@ -46,7 +40,6 @@ class x402SettlementMode(str, Enum):

PRIVATE = "private"
BATCH_HASHED = "batch"
INDIVIDUAL_FULL = "individual"


class CandleOrder(IntEnum):
Expand Down Expand Up @@ -242,7 +235,7 @@ class StreamChunk:
tee_payment_address: Payment address registered for the TEE (final chunk only)
data_settlement_transaction_hash: Transaction hash for the data settlement
transaction, present on the final chunk when available.
data_settlement_blob_id: Walrus blob ID for individual data settlement,
data_settlement_blob_id: Walrus blob ID for data settlement,
present on the final chunk when available.
images: Generated images returned by image-output models, present on the
final chunk when available. Each entry is a ``data:`` URI.
Expand Down Expand Up @@ -430,9 +423,8 @@ class TextGenerationOutput:
data_settlement_transaction_hash: Blockchain transaction hash for
the data settlement transaction. ``None`` when the provider
does not return data settlement metadata.
data_settlement_blob_id: Walrus blob ID for individual data
settlement. ``None`` for private/batch settlement or when the
provider does not return it.
data_settlement_blob_id: Walrus blob ID for data settlement.
``None`` when the provider does not return it.
finish_reason: Reason the model stopped generating
(e.g. ``"stop"``, ``"tool_call"``, ``"error"``).
Only populated for chat requests.
Expand All @@ -453,7 +445,7 @@ class TextGenerationOutput:
"""Blockchain transaction hash for the data settlement transaction. ``None`` when unavailable."""

data_settlement_blob_id: Optional[str] = None
"""Walrus blob ID for individual data settlement. ``None`` when unavailable."""
"""Walrus blob ID for data settlement. ``None`` when unavailable."""

finish_reason: Optional[str] = None
"""Reason the model stopped generating (e.g. ``"stop"``, ``"tool_call"``, ``"error"``). Only populated for chat requests."""
Expand Down
2 changes: 1 addition & 1 deletion stresstest/llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ async def main(private_key: str):

async def run_prompt(prompt: str):
messages = [{"role": "user", "content": prompt}]
await llm.chat(MODEL, messages=messages, max_tokens=50, x402_settlement_mode=og.x402SettlementMode.INDIVIDUAL_FULL)
await llm.chat(MODEL, messages=messages, max_tokens=50, x402_settlement_mode=og.x402SettlementMode.BATCH_HASHED)

latencies, failures = await stress_test_wrapper(run_prompt, num_requests=NUM_REQUESTS)

Expand Down
5 changes: 4 additions & 1 deletion tests/client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,7 @@ def test_settlement_modes_values(self):
"""Test settlement mode enum values."""
assert x402SettlementMode.PRIVATE == "private"
assert x402SettlementMode.BATCH_HASHED == "batch"
assert x402SettlementMode.INDIVIDUAL_FULL == "individual"
assert list(x402SettlementMode) == [
x402SettlementMode.PRIVATE,
x402SettlementMode.BATCH_HASHED,
]
14 changes: 3 additions & 11 deletions tutorials/01-verifiable-ai-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,8 @@ is recorded on-chain:

| Mode | What's Stored | Best For |
|------|--------------|----------|
| `PRIVATE` | Hashes of input and output only | **Privacy** -- proves execution happened without revealing content |
| `PRIVATE` | Payment only; no input/output data | **Privacy** -- keeps inference data off-chain |
| `BATCH_HASHED` | Batch hash of multiple inferences | **Cost efficiency** -- reduces per-call gas costs (default) |
| `INDIVIDUAL_FULL` | Full model info, input, output, and metadata | **Transparency** -- complete auditability for compliance |

Choose based on your requirements:

Expand All @@ -234,13 +233,6 @@ llm_dev = og.agents.langchain_adapter(
x402_settlement_mode=og.x402SettlementMode.BATCH_HASHED,
)

# For production financial applications -- full audit trail
llm_prod = og.agents.langchain_adapter(
private_key=os.environ["OG_PRIVATE_KEY"],
model_cid=og.TEE_LLM.GPT_4_1_2025_04_14,
x402_settlement_mode=og.x402SettlementMode.INDIVIDUAL_FULL,
)

# For privacy-sensitive applications -- minimal on-chain footprint
llm_private = og.agents.langchain_adapter(
private_key=os.environ["OG_PRIVATE_KEY"],
Expand Down Expand Up @@ -354,5 +346,5 @@ if __name__ == "__main__":
models deployed on OpenGradient.
- **Read workflow results**: Use `og.alphasense.create_read_workflow_tool` to read
from scheduled on-chain workflows that run models automatically.
- **Go to production**: Switch settlement mode to `INDIVIDUAL_FULL` and store the
payment hashes and transaction hashes for your compliance records.
- **Go to production**: Store payment hashes and transaction hashes for your
compliance records.
Loading
Loading