Skip to main content

Overview

The sinker policy namespace gates what the AI agent is allowed to do. Policies set hard limits on tip size, how aggressively the agent escalates on retries, how many bundles can be in-flight at once, and more. Settings persist in sinker.policy.json in the working directory. Both the sidecar and the agent read the file once on startup. Restart the stack to apply any changes.
sinker policy <sub-command>
The policy file is partial by design — only the keys you change need to be present. Missing keys resolve silently to built-in defaults. An empty file (or no file at all) means “use all defaults.”

Policy keys

These keys are accepted by sinker policy set and sinker policy reset <key>.

Tip controls

KeyDefaultUnitDescription
max-tip500000lamportsHard ceiling — agent cannot recommend above this regardless of network conditions
max-tip-ratio5.0%Tip cannot exceed N% of the transaction’s transfer value
tip-percentilep75Percentile the agent targets when the network is calm (p50 / p75 / p95 / p99)
stale-after2000msMaximum age of tip oracle data before the agent refuses to proceed

Bundle & retry controls

KeyDefaultUnitDescription
max-retries3Maximum re-submission attempts before a bundle is declared expired
expiry-slots150slotsHow many slots past enqueue the agent keeps retrying before dropping the bundle
escalation-step5000lamportsMaximum tip increase per retry cycle — prevents runaway escalation
max-queue20Maximum in-flight bundles at any time — new enqueues are rejected above this

Throughput controls

KeyDefaultUnitDescription
rate-limit60/minMaximum transactions accepted per minute across all callers
priorityautoPin all bundles to a tier (normal / high / urgent) or let the agent decide (auto)

Commands

sinker policy set <key> <value>

Set a single policy value. The change is written to sinker.policy.json immediately.
sinker policy set max-tip 100000
sinker policy set tip-percentile p95
sinker policy set priority high
sinker policy set max-retries 5
  set max-tip = 100000
  saved → sinker.policy.json
The stack must be restarted for the new value to take effect.

sinker policy show

Print all policy values as a table — current effective value, built-in default, and which keys have been explicitly set.
sinker policy show
┌─ Policy ─────────────────────────────────────────────────────────────────
│  KEY               CURRENT          DEFAULT
│  ──────────────────────────────────────────────────────────────────────
│  max-tip           100000L          500000L          ← set
│  max-tip-ratio     5.0%             5.0%
│  tip-percentile    p75              p75
│  stale-after       2000ms           2000ms
│  max-retries       3                3
│  expiry-slots      150              150
│  escalation-step   5000L            5000L
│  max-queue         20               20
│  rate-limit        60/min           60/min
│  priority          auto             auto
│  ──────────────────────────────────────────────────────────────────────
│  file: sinker.policy.json (1 override)
└──────────────────────────────────────────────────────────────────────────

sinker policy reset [<key>]

Reset a single key back to its built-in default, or reset all keys if no key is given.
# Reset one key
sinker policy reset max-tip

# Reset everything
sinker policy reset
reset without a key writes an empty {} JSON file — all keys will resolve to defaults on next start. The file itself is kept; use sinker policy clear to delete it entirely.

sinker policy clear

Delete the policy file. All settings revert to built-in defaults on the next sidecar or agent start.
sinker policy clear
  delete sinker.policy.json? All settings revert to defaults on next start. [y/N]
Pass --yes / -y to skip the confirmation prompt (useful in CI or setup scripts):
sinker policy clear --yes

sinker policy validate

Check the current effective policy for contradictions and dangerous values.
sinker policy validate
Errors (exit code 1 — block correct operation):
ConditionError
escalation-step > max-tipEvery retry would immediately exceed the tip ceiling
max-tip = 0Jito requires a non-zero tip — all bundles will be rejected
max-tip-ratio ≤ 0Invalid — would block all tips
expiry-slots = 0Bundles expire immediately and can never be submitted
max-queue = 0All enqueues will be rejected
Warnings (informational — do not exit non-zero):
ConditionWarning
stale-after < 400msShorter than one Solana slot — oracle may always appear stale
max-tip-ratio > 100%Tip can exceed the transaction value
max-retries = 0Failed bundles will not be retried
rate-limit = 0All incoming transactions will be rejected
Example output with issues:
  validating policy from sinker.policy.json

  ✗ error: escalation-step (600000L) > max-tip (500000L): every retry would immediately exceed the tip ceiling
  ⚠ warning: stale-after (200ms) is shorter than one slot (~400ms): tip oracle may always appear stale

  1 error(s) found — run `sinker policy set` to fix before starting the stack

sinker policy export [--path <file>]

Export the current effective policy — with all defaults resolved — to a JSON file. Unlike the live policy file (which only stores overrides), the export includes every key. Useful for sharing a policy between Sinker deployments.
# Export to the default path (sinker.policy.json)
sinker policy export

# Export to a custom path
sinker policy export --path /shared/prod.policy.json
  policy exported → /shared/prod.policy.json
  all 10 keys written (defaults resolved)
The exported file can be applied on another machine with sinker policy import.

sinker policy import <file>

Load a policy JSON file, validate it, and apply it as the active policy. Errors block the import; warnings are printed but do not block it.
sinker policy import /shared/prod.policy.json
  imported /shared/prod.policy.json → sinker.policy.json
  restart the stack to apply the new policy
If validation errors are found, the import is aborted and the existing policy is left unchanged:
  ✗ error: max-queue is 0: all enqueues will be rejected

  import aborted — 1 error(s) found in '/shared/prod.policy.json'. Fix and retry.

Storage and load order

The policy file is looked up in this order on every sinker start or sinker up:
  1. Path in SINKER_POLICY_FILE env var — custom override
  2. ./sinker.policy.json — working directory
  3. Built-in defaults — no file required, no warning
# Use a shared policy file across multiple deployments
SINKER_POLICY_FILE=/etc/sinker/policy.json sinker start
The file format is plain JSON. Keys not present resolve to defaults — you only need to store values you change:
{
  "max_tip_lamports": 100000,
  "tip_percentile": "p75",
  "priority": "high"
}

For most production deployments, a conservative starting point:
sinker policy set max-tip 200000        # cap at 200k lamports (~0.0002 SOL)
sinker policy set max-tip-ratio 3       # tip cannot exceed 3% of tx value
sinker policy set escalation-step 5000  # raise by at most 5k lamports per retry
sinker policy set max-retries 4         # up to 4 re-submissions per bundle
sinker policy set max-queue 30          # allow up to 30 in-flight bundles
sinker policy validate                  # confirm no contradictions