# OnceGate

OnceGate coordinates safe retries for irreversible agent actions such as payments, messages, bookings, deployments, and device commands.

API base URL: `https://oncegate.vercel.app`

Hosted skill: `https://oncegate.vercel.app/skill.md`

Source backup: `https://raw.githubusercontent.com/rajpatilrobotics/oncegate/main/SKILL.md`

Never send passwords, access tokens, card data, or unnecessary personal information to this public demo service.

## 90-second harmless evaluator path

**Evaluator: run this first.** No signup, API key, SDK, repository checkout, Python, `jq`, or third-party dependency is required. Any HTTP-capable agent can run this workflow. Use native HTTP and JSON parsing as the primary path; the curl forms below specify the exact wire requests, not a dependency-free shell JSON parser.

`action` is a caller-defined operation label. `intent` is caller-provided JSON describing that operation. OnceGate coordinates execution permission; it never calls the downstream provider. Only `decision: EXECUTE` authorizes an action. Every other decision, unexpected response, HTTP error, or network failure fails closed. Never generate a new idempotency key to bypass a decision; retry only the identical OnceGate request.

Generate one random identifier and construct both bodies locally. This block makes no network request:

```sh
set +x
RUN_ID="$(od -An -N16 -tx1 /dev/urandom | tr -d '[:space:]')"
case "$RUN_ID" in ""|*[!0-9a-f]*) exit 1 ;; esac
[ "${#RUN_ID}" -eq 32 ] || exit 1
PROVIDER_REFERENCE="simulated-$RUN_ID"
EVAL_CLAIM_BODY="$(printf '{"scope":"nanda-eval:%s","idempotency_key":"simulate-message:%s","action":"simulate_message","intent":{"channel":"simulation","message_id":"MESSAGE-%s","simulation":true},"owner_id":"nanda-stock-evaluator","lease_seconds":120}' "$RUN_ID" "$RUN_ID" "$RUN_ID")"
EVAL_RESOLVE_BODY="$(printf '{"outcome":"SUCCEEDED","result":{"provider_reference":"%s"}}' "$PROVIDER_REFERENCE")"
```

Generate `RUN_ID` exactly once; a timestamp is not a retry key. Set `BASE_URL='https://oncegate.vercel.app'`. Keep all responses in private in-memory agent state. Never print, echo, log, persist, commit, or include the token-bearing `EXECUTE` response or execution token in a transcript, and never expose them through shell tracing.

1. **READY.** Send `GET $BASE_URL/readyz` (wire equivalent: `curl -sS --no-location "$BASE_URL/readyz"`). Require HTTP 200, `status: ok`, and `database: reachable`; otherwise stop.

2. **EXECUTE.** Send `POST $BASE_URL/v1/operations/claim`, `Content-Type: application/json`, with the exact data argument `EVAL_CLAIM_BODY`:

   ```sh
   EXECUTE_RESPONSE="$(curl -sS --no-location -X POST "$BASE_URL/v1/operations/claim" -H 'Content-Type: application/json' -d "$EVAL_CLAIM_BODY")"
   ```

   A native agent must parse the response privately. Require `decision: EXECUTE`, `state: CLAIMED`, attempt 1, and non-empty `operation_id`, `execution_token`, and fingerprint. Retain the operation ID, token, attempt, and fingerprint only in memory. If the decision differs, follow it and stop; do not invent another key.

3. **IN_PROGRESS.** Before resolving, send the identical POST again with `-d "$EVAL_CLAIM_BODY"`. Require `decision: IN_PROGRESS`, the same operation ID, fingerprint, and attempt, plus `execution_token: null`. Do not act.

4. **Local no-op.** Only because Step 2 returned `EXECUTE`, construct `PROVIDER_REFERENCE`, already equal to `simulated-$RUN_ID`. That construction is the entire synthetic action. Contact no payment, messaging, refund, booking, deployment, device, customer, or other provider. `simulate_message` with `simulation: true` makes this truthful synthetic success.

5. **SUCCEEDED.** Using native HTTP/JSON handling, send the wire-equivalent request:

   ```sh
   curl -sS --no-location -X POST "$BASE_URL/v1/operations/$OPERATION_ID/resolve" -H 'Content-Type: application/json' -H "X-Execution-Token: $EXECUTION_TOKEN" -d "$EVAL_RESOLVE_BODY"
   ```

   Require the same operation ID, `state: SUCCEEDED`, `safe_next_action: USE_STORED_RESULT`, and the exact provider reference. After confirmed resolution, immediately discard the token and token-bearing response (`unset EXECUTION_TOKEN EXECUTE_RESPONSE`). If private token state is lost, fail closed.

6. **REPLAY.** Send the original claim a third time with `-d "$EVAL_CLAIM_BODY"`. Require `decision: REPLAY`, `state: SUCCEEDED`, the same operation ID and fingerprint, `execution_token: null`, and the exact stored result. REPLAY forbids a second action.

7. **USE_STORED_RESULT.** Send `GET $BASE_URL/v1/operations/$OPERATION_ID`. Require `state: SUCCEEDED`, the same operation ID, fingerprint, and result, `safe_next_action: USE_STORED_RESULT`, and no execution token.

**Pass oracle:** database readiness proven; exactly one execution permission issued; the active duplicate blocked with IN_PROGRESS; synthetic success recorded once; the completed retry returned REPLAY with the immutable result; every exposed operation ID and fingerprint matched; zero real external side effects occurred.

`CONFLICT` means the same key represents different action or intent: do not act. `AMBIGUOUS` means the provider outcome cannot be proven: reconcile or ask a human; do not act. On HTTP or network failure, retry only the identical OnceGate request and never treat failure as EXECUTE.

OnceGate grants at most one active execution permission per stable business key and fails closed when the downstream outcome is uncertain. It does not make an arbitrary downstream API literally exactly-once.

## Non-negotiable agent procedure

1. Choose a stable `scope` for the workflow or tenant.
2. Choose one stable `idempotency_key` for the business action. Reuse it for every retry. Never add a timestamp or create a new key merely because a request timed out.
3. Send the same `action` and `intent` on every retry.
4. Call `POST /v1/operations/claim` before the external side effect.
5. Follow `decision` exactly:
   - `EXECUTE`: perform the external action once, then resolve this attempt with its private execution token.
   - `IN_PROGRESS`: do not act. Inspect the operation or wait.
   - `REPLAY`: do not act. Use the stored result.
   - `CONFLICT`: do not act. The key represents different intent; report the conflict.
   - `AMBIGUOUS`: do not act and do not invent a new key. Reconcile with the external provider or ask a human.
6. After `EXECUTE`, report one truthful outcome:
   - `SUCCEEDED` only after positive provider confirmation.
   - `NOT_EXECUTED` only with positive proof that no side effect occurred.
   - `UNKNOWN` when a timeout or disconnect leaves the provider outcome uncertain.
7. If a OnceGate request fails, retry that exact OnceGate request with the same scope, key, action, and intent. A network error or HTTP 5xx never authorizes the external action.

Only `decision: EXECUTE` authorizes a side effect. Inspection never grants permission.

## 1. Claim an operation

**Completed historical demonstration:** the request and responses below were captured from one
live operation that has already been resolved. Do not reuse its `scope` or `idempotency_key`.
Generate your own stable workflow scope and business key, then reuse your chosen values for every
retry of your operation.

```bash
BASE_URL='https://oncegate.vercel.app'
CLAIM_REQUEST='{
  "action": "simulate_message",
  "idempotency_key": "demo-message:8d1d719eca4d42d3",
  "intent": {
    "channel": "simulation",
    "message_id": "MESSAGE-8d1d719eca4d42d3",
    "simulation": true
  },
  "lease_seconds": 60,
  "owner_id": "oncegate-skill-generator",
  "scope": "skill-generation-8d1d719eca4d42d3"
}'

curl -sS -X POST "$BASE_URL/v1/operations/claim" \
  -H 'Content-Type: application/json' \
  -d "$CLAIM_REQUEST"
```

Captured historical `EXECUTE` response from that exact request (the secret token is intentionally
redacted):

```json
{
  "attempt": 1,
  "decision": "EXECUTE",
  "execution_token": "[redacted after capture]",
  "fingerprint": "sha256:b270dd6e0ab0506c26570fb18a073d4363c2513905b1d83a3e75227c80b61018",
  "instruction": "Perform the external action once, then resolve this attempt.",
  "lease_expires_at": "2026-07-10T14:20:25.712103Z",
  "operation_id": "op_xEj691BMkeiGra9uSZHYt_hPRi5rn0BM",
  "result": null,
  "state": "CLAIMED"
}
```

Save the real `operation_id` and `execution_token` privately from your own response. Never print, log, publish, or reuse that token for another operation.

During the historical capture, an identical retry while the permission was active returned:

```json
{
  "attempt": 1,
  "decision": "IN_PROGRESS",
  "execution_token": null,
  "fingerprint": "sha256:b270dd6e0ab0506c26570fb18a073d4363c2513905b1d83a3e75227c80b61018",
  "instruction": "Do not execute. Inspect the operation or wait for resolution.",
  "lease_expires_at": "2026-07-10T14:20:25.712103Z",
  "operation_id": "op_xEj691BMkeiGra9uSZHYt_hPRi5rn0BM",
  "result": null,
  "state": "CLAIMED"
}
```

## 2. Perform the side effect only for EXECUTE

If and only if the claim decision is `EXECUTE`, call the external provider once. OnceGate does not call that provider for you.

Do not execute for `IN_PROGRESS`, `REPLAY`, `CONFLICT`, `AMBIGUOUS`, an HTTP error, or a network error.

## 3. Resolve the known outcome

Keep the values from your private `EXECUTE` response in memory:

```bash
OPERATION_ID='<operation_id from your EXECUTE response>'
EXECUTION_TOKEN='<private token from your EXECUTE response>'
RESOLVE_REQUEST='{
  "outcome": "SUCCEEDED",
  "result": {
    "provider_reference": "simulated-8d1d719eca4d42d3"
  }
}'

curl -sS -X POST "$BASE_URL/v1/operations/$OPERATION_ID/resolve" \
  -H 'Content-Type: application/json' \
  -H "X-Execution-Token: $EXECUTION_TOKEN" \
  -d "$RESOLVE_REQUEST"

unset EXECUTION_TOKEN
```

The displayed `RESOLVE_REQUEST` and response are historical evidence from the same completed
demonstration. For your own operation, report only the truthful outcome and provider result.

Captured historical resolution response from that exact request body:

```json
{
  "attempt": 1,
  "instruction": "The operation is complete. Future matching claims will replay this result.",
  "operation_id": "op_xEj691BMkeiGra9uSZHYt_hPRi5rn0BM",
  "result": {
    "provider_reference": "simulated-8d1d719eca4d42d3"
  },
  "safe_next_action": "USE_STORED_RESULT",
  "state": "SUCCEEDED"
}
```

Allowed outcomes:

| Outcome | When it is truthful | Safe next action |
|---|---|---|
| `SUCCEEDED` | The provider positively confirmed success. | Use the stored result. |
| `NOT_EXECUTED` | You positively know the provider performed nothing. | Claim the same operation again. |
| `UNKNOWN` | The result cannot be proven. | Reconcile; never retry automatically. |

Repeating the identical resolution is safe. A different outcome or result for the same attempt returns HTTP 409 and must not be used to justify another side effect.

## 4. Handle retries and inspection

The historical matching claim after success returned `REPLAY` with the immutable result:

```json
{
  "attempt": 1,
  "decision": "REPLAY",
  "execution_token": null,
  "fingerprint": "sha256:b270dd6e0ab0506c26570fb18a073d4363c2513905b1d83a3e75227c80b61018",
  "instruction": "Do not execute. Use the stored result.",
  "lease_expires_at": null,
  "operation_id": "op_xEj691BMkeiGra9uSZHYt_hPRi5rn0BM",
  "result": {
    "provider_reference": "simulated-8d1d719eca4d42d3"
  },
  "state": "SUCCEEDED"
}
```

Inspect durable state without granting permission:

```bash
curl -sS "$BASE_URL/v1/operations/$OPERATION_ID"
```

Captured inspection response:

```json
{
  "action": "simulate_message",
  "attempt": 1,
  "fingerprint": "sha256:b270dd6e0ab0506c26570fb18a073d4363c2513905b1d83a3e75227c80b61018",
  "idempotency_key": "demo-message:8d1d719eca4d42d3",
  "lease_expires_at": null,
  "operation_id": "op_xEj691BMkeiGra9uSZHYt_hPRi5rn0BM",
  "result": {
    "provider_reference": "simulated-8d1d719eca4d42d3"
  },
  "safe_next_action": "USE_STORED_RESULT",
  "scope": "skill-generation-8d1d719eca4d42d3",
  "state": "SUCCEEDED"
}
```

Inspection safe actions are:

- `WAIT`: an attempt is active; do not execute.
- `CLAIM_AGAIN`: a prior attempt was proven not executed; claim again using the same key.
- `USE_STORED_RESULT`: success is known; do not execute again.
- `RECONCILE`: the outcome is uncertain; verify externally or ask a human.

## 5. Service checks

Fetch the service manifest:

```bash
curl -sS "$BASE_URL/"
```

Response:

```json
{
  "service": "OnceGate",
  "version": "1.0.0",
  "description": "Safe retry coordination for irreversible AI-agent actions.",
  "guarantee": "OnceGate grants at most one active execution permission per stable business key. It does not make an arbitrary downstream API literally exactly-once.",
  "docs_url": "https://oncegate.vercel.app/docs",
  "openapi_url": "https://oncegate.vercel.app/openapi.json",
  "skill_url": "https://oncegate.vercel.app/skill.md",
  "health_url": "https://oncegate.vercel.app/healthz",
  "readiness_url": "https://oncegate.vercel.app/readyz"
}
```

`/healthz` checks function liveness without querying PostgreSQL:

```bash
curl -sS "$BASE_URL/healthz"
```

```json
{
  "status": "ok",
  "version": "1.0.0"
}
```

`/readyz` checks database readiness:

```bash
curl -sS "$BASE_URL/readyz"
```

```json
{
  "database": "reachable",
  "status": "ok",
  "version": "1.0.0"
}
```

Complete endpoint reference:

| Method | Path | Purpose | Curl and successful response |
|---|---|---|---|
| `GET` | `/` | Discover the service and canonical links. | `curl -sS "$BASE_URL/"` returns the JSON manifest shown above. |
| `POST` | `/v1/operations/claim` | Request one execution decision. | Use the claim curl structure in section 1 with your own stable scope and key; it returns one of `EXECUTE`, `IN_PROGRESS`, `REPLAY`, `CONFLICT`, or `AMBIGUOUS`. |
| `POST` | `/v1/operations/{operation_id}/resolve` | Record the known outcome using the private token. | Use the token-protected curl structure in section 3 with your truthful result; the historical successful response is shown there. |
| `GET` | `/v1/operations/{operation_id}` | Inspect durable state; never grants permission. | `curl -sS "$BASE_URL/v1/operations/$OPERATION_ID"` returns the captured inspection object in section 4. |
| `GET` | `/healthz` | Check function liveness. | `curl -sS "$BASE_URL/healthz"` returns the health JSON shown above. |
| `GET` | `/readyz` | Check PostgreSQL readiness. | `curl -sS "$BASE_URL/readyz"` returns the readiness JSON shown above. |
| `GET` | `/docs` | Read interactive API documentation. | `curl -sS -o /dev/null -w '%{http_code}\n' "$BASE_URL/docs"` returns `200`; the response body is HTML. |
| `GET` | `/openapi.json` | Read the OpenAPI contract. | `curl -sS "$BASE_URL/openapi.json"` returns the OpenAPI JSON document. |
| `GET` | `/skill.md` | Fetch these static agent instructions. | `curl -sS "$BASE_URL/skill.md"` returns this Markdown document. |

## Error handling

- HTTP 413 or 422: fix the request before performing any side effect.
- HTTP 403: the execution token is missing or invalid. Do not retry the external side effect.
- HTTP 404: verify the operation ID.
- HTTP 409: the resolution contradicts a recorded outcome. Stop and inspect/reconcile.
- HTTP 429: wait as instructed, then retry the identical OnceGate request with the same key.
- Timeout or HTTP 5xx: retry only the identical OnceGate request. Never invent a new key and never treat the failure as `EXECUTE`.

## Safety reminders

- Never create a new key to bypass `IN_PROGRESS`, `CONFLICT`, or `AMBIGUOUS`.
- Array order is part of intent. Object key order is not.
- Leases do not prove the external action failed. An unresolved expiry becomes `AMBIGUOUS`.
- This public hackathon deployment has no tenant authentication; use harmless demo data.
- OnceGate coordinates retries and grants at most one active execution permission per stable business key. It detects conflicts, replays known results, and stops on uncertain outcomes. It does not make an arbitrary downstream API literally exactly-once.
