Skip to main content

Transactions

Transactions group multiple writes and deletes into an atomic unit. Either all operations succeed, or none do.

Beginning a Transaction

tx = client.begin_transaction()

Parameters

ParameterTypeDefaultDescription
timeout_msint | None30000Transaction timeout in milliseconds
namespacestr | NoneClient defaultNamespace for this transaction

Writing State

tx.write(
agent_id="my-agent",
key="memory",
value={"fact": "Some information"},
)

Parameters

ParameterTypeDescription
agent_idstrAgent identifier
keystrState key
valueDict[str, Any]JSON-compatible dictionary

The value must be a dictionary. Nested structures, lists, and primitive types are supported.

Deleting State

tx.delete(agent_id="my-agent", key="memory")

Deletes create a tombstone record. The key will no longer exist, but the delete event is recorded in the log.

Committing

commit_ts = tx.commit()
print(f"Committed at timestamp {commit_ts}")

Returns the commit timestamp (monotonic integer).

Aborting

tx.abort()

Aborts discard all staged operations. No state changes occur.

The recommended pattern uses a context manager:

with client.begin_transaction() as tx:
tx.write(agent_id="agent", key="key1", value={"a": 1})
tx.write(agent_id="agent", key="key2", value={"b": 2})
# Commits automatically on exit

If an exception occurs, the transaction is automatically aborted:

with client.begin_transaction() as tx:
tx.write(agent_id="agent", key="key", value={"x": 1})
raise ValueError("Something went wrong")
# Transaction is aborted, state unchanged

Multiple Operations

A single transaction can contain multiple writes and deletes:

with client.begin_transaction() as tx:
tx.write(agent_id="agent", key="step:1", value={"action": "start"})
tx.write(agent_id="agent", key="step:2", value={"action": "process"})
tx.delete(agent_id="agent", key="temp:scratch")
tx.write(agent_id="agent", key="step:3", value={"action": "finish"})

All operations are applied atomically at commit.

Transaction Timeouts

Transactions have a server-side timeout. If not committed within the timeout, the transaction is automatically aborted.

# 5 second timeout
tx = client.begin_transaction(timeout_ms=5000)

Error Handling

from statehouse import TransactionError

try:
with client.begin_transaction() as tx:
tx.write(agent_id="agent", key="key", value={"x": 1})
except TransactionError as e:
print(f"Transaction failed: {e}")

Common errors:

  • Transaction already committed: Cannot modify after commit
  • Transaction already aborted: Cannot modify after abort
  • Transaction timeout: Server aborted due to timeout