Read operations

Learn how to declare state-observing operations with @read in the AgentIdem Nebutex SDK and understand how reads appear in AgentIdem traces.

Read operations represent actions that observe state without changing it.

Use @read for operations that retrieve or inspect information.

Examples include:

  • fetching an order
  • reading a database record
  • checking whether a user exists
  • retrieving account state
  • loading configuration
  • reading external API data
  • checking the status of a resource

Basic read

Import read from agentidem and decorate the function that performs the state-observing operation.

from agentidem import read

@read
def get_order(order_id: str):
    return database.get(order_id)

The function can still be called normally from your agent code.

def run_agent(order_id: str):
    order = get_order(order_id)

    return order

AgentIdem records the decorated call as a READ operation in the execution trace.

What AgentIdem records

A traced read can include information such as:

  • operation name
  • operation kind
  • arguments
  • result
  • error
  • execution status
  • observation state
  • timestamps

The operation kind for a read is:

READ

Reads are not side effects

A read observes state.

It does not represent a state-changing side effect.

For example:

@read
def get_payment(payment_id: str):
    return database.get_payment(payment_id)

Calling get_payment multiple times may produce multiple trace entries, but those calls are not treated as duplicate side effects.

AgentIdem's duplicate side effect detection is focused on successful write operations.

Read and write together

A typical agent may perform reads before deciding whether a write is necessary.

from agentidem import read, write

@read
def get_order(order_id: str):
    return database.get(order_id)

@write(identity=lambda order_id: order_id)
def create_order(order_id: str):
    return external_service.create_order(order_id)

def run_agent(order_id: str):
    order = get_order(order_id)

    if order is None:
        return create_order(order_id)

    return order

In the trace, AgentIdem can distinguish:

READ  get_order
WRITE create_order

This distinction makes it easier to understand which operations only observed state and which operations could have changed the outside world.

Read failures

A read can fail during execution.

For example:

@read
def get_order(order_id: str):
    raise RuntimeError("Database unavailable")

A failed read is recorded as a failed operation.

The failure may affect the rest of the agent execution, but it is still not treated as a completed side effect.

Reads in traces

Consider an agent that checks a payment before issuing a refund.

from agentidem import read, write

@read
def get_payment(payment_id: str):
    return payments.get(payment_id)

@write(identity=lambda payment_id: payment_id)
def refund(payment_id: str):
    return payments.refund(payment_id)

def refund_agent(payment_id: str):
    payment = get_payment(payment_id)

    if payment["status"] == "paid":
        return refund(payment_id)

    return "no_refund"

A trace might contain:

READ   get_payment
WRITE  refund

The read provides context for the execution, while the write represents the operation that may change external state.

Reads and fault scenarios

AgentIdem can record reads while running controlled fault scenarios against an agent.

The important distinction remains:

READ

observes state.

WRITE

may change state.

Fault scenarios that test side effect safety are primarily concerned with what happens around state-changing operations.

Reads still appear in traces so you can understand the full sequence of execution.

When to use @read

Use @read when a function:

  • retrieves information
  • inspects current state
  • checks whether something exists
  • fetches data used for a later decision
  • does not intentionally change external state

Do not use @read for operations that create, update, delete, send, publish, charge, refund, provision, or otherwise modify external state.

Those operations should use @write.

Next steps