# Agent Toolflow

This project exposes deterministic CLI operations intended for LLM/agent orchestration. The agent conversation UX can vary; the backend/tool flow should remain explicit and stable.

{% hint style="info" %}
Goal

* Be the execution layer ("pickaxes"), not the chat layer.
* Let any agent discover capabilities, validate intent, create orders, and monitor status.
  {% endhint %}

## Commands

* `pnpm cli agent:capabilities`
* `pnpm cli agent:schemas`
* `pnpm cli agent:swap:plan`
* `pnpm cli agent:swap:quote`
* `pnpm cli agent:swap:create`
* `pnpm cli agent:swap:execute`
* `pnpm cli agent:swap:status`
* `pnpm cli agent:support:create`
* `pnpm agent:rpc` (HTTP JSON-RPC server)

All agent commands return JSON with:

* `ok`
* `operation`
* `state`
* `missingInputs`
* `validationErrors`
* `nextActions`
* `data`

For correlation and stateless runs:

* `--request-id <id>` echoes into responses.
* `--stateless` disables local state read/write.
* `--idempotency-key <key>` is supported on `agent:swap:create` and `agent:swap:execute`.

## JSON-RPC Transport

Start:

```bash
pnpm agent:rpc
```

Endpoints:

* `GET /health`
* `POST /rpc`

Auth:

* Optional token header: `x-agent-rpc-token: <AGENT_RPC_TOKEN>`

JSON-RPC methods:

* `swapper.capabilities`
* `swapper.schemas`
* `swapper.swap.plan`
* `swapper.swap.quote`
* `swapper.swap.create`
* `swapper.swap.execute`
* `swapper.swap.status`
* `swapper.support.create`

Example JSON-RPC call:

```json
{
  "jsonrpc": "2.0",
  "id": "req-1001",
  "method": "swapper.swap.execute",
  "params": {
    "direction": "x2u",
    "chain": "arbitrum",
    "amount": "0.8",
    "to": "0x1111111111111111111111111111111111111111",
    "idempotency-key": "swap_user123_req1001"
  }
}
```

## Canonical Swap Flow (XMR -> USDC or USDC -> XMR)

{% stepper %}
{% step %}

### Discovery

Call `agent:capabilities`.
{% endstep %}

{% step %}

### Intent normalization

Call `agent:swap:plan` with any known fields.

If `state=needs_input` or `state=needs_destination`, collect missing fields from user.
{% endstep %}

{% step %}

### Price

Call `agent:swap:quote`.
{% endstep %}

{% step %}

### Order creation

Call `agent:swap:create`.

* Read `data.fundingInstructions` and ask user to send exact funds.
* Use `idempotency-key` to make retries safe.
* If key is reused with different payload, state becomes `idempotency_conflict`.
* Optional shortcut: call `agent:swap:execute` to do quote+create in one step.
  {% endstep %}

{% step %}

### Status loop

Poll with `agent:swap:status` until terminal:

* `completed`
* `terminal_failure`
  {% endstep %}

{% step %}

### Failure fallback

If terminal failure, call `agent:support:create`.
{% endstep %}
{% endstepper %}

## Important Design Notes

{% hint style="info" %}

* Agents do not need custody to operate: create order first, then request user funding using deposit instructions.
* Destination address is required before order creation.
* Session provenance is explicit in payloads (`sessionSource`).
* The tool only exposes execution primitives; agent dialogue policy is out of scope.
  {% endhint %}

## LLM Agent Spec (Scrape-Friendly)

Machine-readable spec file: `docs/LLM_AGENT_SPEC.json`

```json
{
  "transport": "jsonrpc 2.0",
  "rpc_url": "http://127.0.0.1:8790/rpc",
  "health_url": "http://127.0.0.1:8790/health",
  "methods": [
    "swapper.capabilities",
    "swapper.schemas",
    "swapper.swap.plan",
    "swapper.swap.quote",
    "swapper.swap.create",
    "swapper.swap.execute",
    "swapper.swap.status",
    "swapper.support.create"
  ],
  "idempotency": {
    "fields": ["idempotency-key"],
    "applies_to": ["swapper.swap.create", "swapper.swap.execute"]
  }
}
```

## Example User-Agent-US Workflow

{% stepper %}
{% step %}

### User -> Agent

"Swap 0.8 XMR to USDC."
{% endstep %}

{% step %}

### Agent -> Us (`swapper.swap.plan`)

params: `{ "direction":"x2u", "chain":"arbitrum", "amount":"0.8" }`
{% endstep %}

{% step %}

### Us -> Agent

state: `needs_destination`\
next action: ask destination address.
{% endstep %}

{% step %}

### Agent -> User

"Where should I send the USDC on Arbitrum?"
{% endstep %}

{% step %}

### User -> Agent

"Send to 0xabc...1234"
{% endstep %}

{% step %}

### Agent -> Us (`swapper.swap.execute`)

params include:

* `direction=x2u`
* `chain=arbitrum`
* `amount=0.8`
* `to=0xabc...1234`
* `idempotency-key=swap_user123_20260212_01`
  {% endstep %}

{% step %}

### Us -> Agent

state: `waiting_for_funding`\
data:

* `order.orderId`
* `fundingInstructions.depositAddress`
* `fundingInstructions.amountDisplay`
* `fundingInstructions.expiresAt`
  {% endstep %}

{% step %}

### Agent -> User

"Please send exactly X XMR to address Y before expiry Z."
{% endstep %}

{% step %}

### Agent -> Us (`swapper.swap.status`, loop)

Poll until `completed` or `terminal_failure`.
{% endstep %}

{% step %}

### Us -> Agent

* `completed` -> final success payload.
* `terminal_failure` -> agent should call `swapper.support.create`.
  {% endstep %}

{% step %}

### Agent -> User

* Success: "Swap complete. USDC delivered."
* Failure: "Swap failed/expired/refunded. I opened support ticket ."
  {% endstep %}
  {% endstepper %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.xmrtousdc.xyz/agent-toolflow.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
