Drop the integration folder into your agent's project. The app generates the full .env block for you. Open the Agents tab, create a new connection, tap Copy .env block, paste. Everything pre-filled.
In practice: point your agent at the folder and tell it to read the contents. It figures out the rest on its own. We tested funding and x402 end-to-end by asking the agent to run both, no manual steps, no guidance needed. It just worked.
warm_vault_auth.py · tg_bot.py · .env.example · SETUP.md · demo scripts
Python 3.10+ required. Install the three packages the skill uses.
pip install solana solders requests
Open the Tally app → Agents tab → New Connection. The wizard walks you through Telegram bot setup and generates a session keypair. At the end, tap Copy .env block.
That block has everything pre-filled: Telegram token, chat ID, session private key, vault address, and deep-link secret. Paste it directly into tally_integration/.env.
Your vault needs SOL for gas and USDC for agent sessions. On devnet, both are free.
# SOL airdrop (replace with your vault address from Tally home screen)
solana airdrop 1 <YOUR_VAULT_ADDRESS> --url devnet
# USDC, use the Circle faucet (also creates the required USDC token account)
# https://faucet.circle.com
Test the full x402 flow end-to-end. The agent hits the live paywalled endpoint, your phone gets a Telegram notification, you tap your card, real USDC moves on-chain, signal returned.
cd tally_integration
python3 run_x402_demo.py
Expected output:
→ GET tally.lll.mk/api/signal
← 402 Payment Required
→ Telegram notification sent
← Card tap received · Session funded
→ 0.1 USDC sent on-chain (tx: 3xKp...)
→ Waiting for propagation...
→ GET /api/signal + X-Tally-Session + X-Tally-Tx
← 200 OK
signal: BULLISH | SOL/USDC | entry · target · stop loss · R:R returned
→ Funds swept back to vault
Request funding and execute a task. One card tap authorizes a budget for a time window, set with ttl in seconds. Every call inside that window reuses the same session, no re-tap.
from warm_vault_auth import request_funding, is_session_active, return_funds
# Sends Telegram notification, waits for one card tap.
# ttl=3600 means the tap authorizes spending for the next hour.
session = request_funding(
amount_usdc=5.0,
task_description="Research flight prices to Tokyo",
ttl=3600,
)
# Reuse the session for every call inside the window. Only re-tap once it expires.
while work_remaining():
if not is_session_active(session):
session = request_funding(amount_usdc=5.0, task_description="more work", ttl=3600)
do_one_call(session)
# Sweep residual back to vault when done
return_funds(session)
Hit a paywalled x402 API automatically:
from warm_vault_auth import request_with_payment
# Full x402 flow: 402 → card tap → USDC on-chain → signal → sweep back
result = request_with_payment(
url="https://tally.lll.mk/api/signal",
amount_usdc=1.0,
task_description="Fetch SOL/USDC market signal",
return_funds_after=True,
)
if result["ok"]:
signal = result["data"]["signal"]
print(signal["signal"]) # BULLISH / BEARISH
print(signal["entry"]) # entry price
The flow above funds a fresh session per task and sweeps the residual back. The second model skips the per-task tap entirely: with one card tap the user pre-authorizes a capped, time-boxed budget on Solana's allowances program (a FixedDelegation). The agent then pays merchants straight from the vault within that budget, no further taps. The cap and expiry are enforced on-chain and the cap decrements per payment, so the unspent remainder never leaves the cold vault — nothing to sweep back. Revoke one agent, or all of them, instantly.
No budget yet? The agent proposes one. The user gets a Telegram deep link that opens the app's Authorize Budget screen pre-filled, and approves with a single card tap.
from warm_vault_auth import request_budget, wait_for_budget
# Propose a budget. ttl_seconds accepts seconds or "7d" / "24h".
# Sends the user a Telegram deep link → Authorize Budget screen → one card tap.
req = request_budget(amount_usdc=15, ttl_seconds="7d", reason="60 signal API calls")
# Optionally block until approved (or poll budget_status() later).
budget = wait_for_budget(timeout_seconds=600) # dict if approved, None on timeout
With a budget active, the agent pays directly — no tap, no sweep:
from warm_vault_auth import budget_status, pay_from_budget, request_with_payment
# Inspect the active budget (reads the on-chain FixedDelegation).
b = budget_status()
# → {"remaining_usdc": 14.0, "expiry_ts": 1769900000, "active": True}
# Pay a payee straight from the vault, within the cap. No card tap.
# Signed by the session key; the program checks cap + expiry and decrements on-chain.
sig = pay_from_budget(destination_pubkey="<PAYEE>", amount_usdc=1.0)
# x402 in budget mode: pay the endpoint directly, no tap, no sweep.
result = request_with_payment(
url="https://tally.lll.mk/api/signal",
amount_usdc=1.0,
source="budget",
)