コンテンツへスキップ
最終更新:

Track and Measure Agent Behavior

When an agent transacts on the XRP Ledger, its activity is permanently recorded on a public ledger. That is a feature, not a side effect — but only if you design for it. Without attribution, an agent's transactions are indistinguishable from human-initiated ones. You cannot answer basic operational questions: how many transactions did the agent send today? Which workflow triggered this payment? Did the agent act within the boundaries you set?

The XRP Ledger provides two lightweight fields that turn the ledger into a queryable audit trail: SourceTag for attribution, and Memos for structured metadata. A third mechanism — WebSocket event subscriptions — lets an agent or monitoring process react to on-chain activity in real time. Used together, they give you a complete picture of agent behavior directly from the on-chain record, independent of application logs that can be lost, rotated, or tampered with.

These patterns apply to every agentic workflow on the XRP Ledger — payments, trading, escrow, and any domain skill built on the shared Wallet skill.


SourceTag — agent attribution

Every XRP Ledger transaction supports a SourceTag field: a 32-bit unsigned integer that identifies the originating application or workflow. The XRPL Agent Wallet skill applies a default SourceTag (20260530) automatically to every transaction that passes through the signing ceremony — you do not need to set it manually. All domain skills (Payments, and future skills) are tagged consistently without any per-skill configuration.

To use a custom value — for example, to distinguish transactions from different agents in the same deployment — set SourceTag on the transaction object before passing it to the Wallet skill. The skill respects any value already present and only applies the default when the field is absent. Setting SourceTag to 0 explicitly suppresses the default.

from xrpl.models.transactions import Payment
from xrpl.utils import xrp_to_drops
from xrpl.transaction import submit_and_wait

# Override only when you need a custom tag — the Wallet skill sets
# 20260530 automatically when SourceTag is absent.
CUSTOM_SOURCE_TAG = 99991234  # your team's registered value

payment = Payment(
    account=wallet.address,
    amount=xrp_to_drops(10),
    destination=DESTINATION,
    source_tag=CUSTOM_SOURCE_TAG,
)
response = submit_and_wait(payment, client, wallet)
print(f"Hash: {response.result['hash']}")

The default tag (20260530) lets you filter all XRPL AI Starter Kit agentic transactions on-chain using any XRPL data API or block explorer, across every domain skill. Use a custom tag when you need per-agent or per-deployment attribution beyond the default.


Memos — structured on-chain metadata

The Memos field carries arbitrary structured metadata alongside every transaction. Where SourceTag answers "which agent sent this?", Memos answer "why, in what context, and as part of which task?" Combining the two gives you a correlation key between your application logs and the on-chain record.

Memo values must be hex-encoded. The pattern below encodes a JSON payload that links each transaction to a specific agent, session, action, and task ID.

import json
from xrpl.models.transactions import Payment
from xrpl.models.transactions.transaction import Memo
from xrpl.utils import xrp_to_drops
from xrpl.transaction import submit_and_wait

def build_memo(agent_id: str, session_id: str, action: str, task_id: str) -> Memo:
    payload = json.dumps({
        "agent_id":   agent_id,
        "session_id": session_id,
        "action":     action,
        "task_id":    task_id,
    }, separators=(",", ":"))
    return Memo(memo_data=payload.encode().hex().upper())

payment = Payment(
    account=wallet.address,
    amount=xrp_to_drops(25),
    destination=DESTINATION,
    source_tag=CUSTOM_SOURCE_TAG,
    memos=[build_memo(
        agent_id="invoice-agent-v1",
        session_id="sess-abc123",
        action="pay_invoice",
        task_id="inv-00789",
    )],
)
response = submit_and_wait(payment, client, wallet)
print(f"Hash: {response.result['hash']}")

To decode memos from a fetched transaction:

import json

def decode_memo(memo_hex: str) -> dict:
    return json.loads(bytes.fromhex(memo_hex).decode("utf-8"))

for entry in response.result.get("Memos", []):
    data = decode_memo(entry["Memo"]["MemoData"])
    print(data)
    # {"agent_id": "invoice-agent-v1", "session_id": "sess-abc123", ...}

Security note: The XRPL Agent Wallet skill decodes memos on incoming transactions for display only. Memo contents are never treated as instructions to the agent — this is a prompt-injection guard. Never write code that acts on memo contents without first routing the action through the full signing ceremony.


WebSocket monitoring — react to on-chain events

The XRP Ledger's WebSocket API lets an agent — or a dedicated monitoring process — subscribe to an account's transactions in real time. This is the right pattern for triggering downstream agent steps when an incoming payment arrives, an escrow completes, or any other account event occurs.

import asyncio
import json
import websockets

TESTNET_WS = "wss://s.altnet.rippletest.net:51233"

async def monitor_account(address: str):
    async with websockets.connect(TESTNET_WS) as ws:
        await ws.send(json.dumps({
            "command":  "subscribe",
            "accounts": [address],
        }))
        print(f"Subscribed to transactions for {address}")

        async for message in ws:
            event = json.loads(message)
            if event.get("type") == "transaction":
                tx   = event.get("transaction", {})
                meta = event.get("meta", {})
                if meta.get("TransactionResult") == "tesSUCCESS":
                    print(f"Confirmed: {tx.get('TransactionType')} | {tx.get('hash')}")
                    # Trigger your agent's next step here.

asyncio.run(monitor_account(wallet.address))

For production deployments, run the monitoring process separately from the agent process so a crashed agent does not stop telemetry collection. Persist the event stream to your logging infrastructure alongside the decoded memo payload for a complete, correlated audit trail.


Where to go next