TEMPORAL INTEGRATION

Purple Flea for Temporal

Temporal is the durable workflow engine that ensures your code runs exactly once, with automatic retries, state persistence, and fault tolerance. Combined with Purple Flea's financial APIs, you get trading agents that never lose state — even across failures, restarts, and multi-day workflows.

Get API Key — Free View API Reference

Why Temporal for Financial Agents

Financial workflows have requirements that crash naive agent implementations. Temporal solves all of them at the infrastructure level.

🎯

Exactly-Once Execution

Network timeouts and agent crashes can cause a naive implementation to fire a trade twice — once that succeeds server-side but whose response is never received. Temporal's workflow history guarantees that each execute_trade activity runs exactly once, even if the worker crashes mid-execution.

No double trades
🔄

Automatic Retry with Backoff

Purple Flea API calls can fail transiently — rate limits, network blips, server restarts. Instead of writing brittle retry loops, Temporal activities are automatically retried with configurable exponential backoff. Your workflow simply moves forward when the activity succeeds.

Resilient by default
😴

Long-Running Workflows

A "rebalance monthly" DCA workflow can issue a trade, call workflow.sleep(timedelta(days=30)), and wake up a month later to execute the next trade — with full state persistence in between. No cron job, no database, no missed executions.

Sleep for 365 days

Architecture

A Temporal-powered Purple Flea agent has three layers: activities wrapping API calls, workflows orchestrating logic, and the Temporal server persisting all state.

Your Code
DCAWorkflow
RiskMonitorWorkflow
EscrowCoordinatorWorkflow
DomainManagerWorkflow
↓ calls
Activities
execute_trade()
get_portfolio()
wallet_balance()
create_escrow()
casino_bet()
↓ wrapped calls
Purple Flea API
https://purpleflea.com/api/v1/...
↕ state & history
Temporal Server
Workflow History
Activity Queue
Timer Service
Worker Registry

Activities

Each Purple Flea API call is wrapped as a Temporal @activity.defn function. Activities are retried on failure, and their results are persisted in workflow history — so a restarted worker never re-executes a completed activity.

Workflows

Workflow functions orchestrate activities using normal Python control flow — loops, conditionals, await. Workflow code must be deterministic (no random, no datetime.now()) but otherwise reads like ordinary sequential code.

Workers

Workers are long-running Python processes that poll Temporal for tasks. You can run them on any server — your VPS, a container, Lambda. Scale horizontally by running more workers; Temporal distributes tasks automatically.

Python Example

A complete Temporal workflow using the Python SDK — Purple Flea activities with automatic retry, plus a DCA workflow that runs for 52 weeks.

purple_flea_workflow.py
from temporalio import activity, workflow
from temporalio.client import Client
from temporalio.worker import Worker
from datetime import timedelta
import requests
import os

PURPLE_FLEA_KEY = os.environ["PURPLE_FLEA_API_KEY"]
BASE_URL = "https://purpleflea.com/api/v1"

# ─── ACTIVITIES ───────────────────────────────────────────────────────────────

@activity.defn
async def execute_trade(symbol: str, side: str, size_usd: float) -> dict:
    """Purple Flea trade wrapped as Temporal activity — auto-retried on failure"""
    response = requests.post(
        f"{BASE_URL}/trade",
        json={"symbol": symbol, "side": side, "size": size_usd, "leverage": 2},
        headers={"Authorization": f"Bearer {PURPLE_FLEA_KEY}"}
    )
    response.raise_for_status()
    return response.json()


@activity.defn
async def get_portfolio() -> dict:
    """Fetch all open positions and unrealized PnL"""
    response = requests.get(
        f"{BASE_URL}/portfolio",
        headers={"Authorization": f"Bearer {PURPLE_FLEA_KEY}"}
    )
    response.raise_for_status()
    return response.json()


@activity.defn
async def close_all_positions() -> dict:
    """Emergency close — exits all positions at market"""
    response = requests.post(
        f"{BASE_URL}/trade/close-all",
        headers={"Authorization": f"Bearer {PURPLE_FLEA_KEY}"}
    )
    response.raise_for_status()
    return response.json()


@activity.defn
async def create_escrow(amount_usd: float, counterparty_id: str, condition: str) -> dict:
    """Create trustless escrow with Purple Flea (1% fee, 15% referral)"""
    response = requests.post(
        f"{BASE_URL}/escrow/create",
        json={"amount_usd": amount_usd, "counterparty": counterparty_id, "condition": condition},
        headers={"Authorization": f"Bearer {PURPLE_FLEA_KEY}"}
    )
    response.raise_for_status()
    return response.json()


# ─── WORKFLOWS ────────────────────────────────────────────────────────────────

@workflow.defn
class DCAWorkflow:
    """Dollar-cost average into BTC every week for 52 weeks"""

    @workflow.run
    async def run(self, weekly_amount: float):
        for week in range(52):
            result = await workflow.execute_activity(
                execute_trade,
                args=["BTC-PERP", "long", weekly_amount],
                schedule_to_close_timeout=timedelta(minutes=5),
                retry_policy=RetryPolicy(
                    backoff_coefficient=2.0,
                    maximum_attempts=10,
                    maximum_interval=timedelta(minutes=2)
                )
            )
            # Persist weekly result in workflow history
            workflow.logger.info(f"Week {week+1}: bought BTC at {result['entry_price']}")
            # Sleep for exactly 7 days — Temporal timer, not OS sleep
            await workflow.sleep(timedelta(days=7))


@workflow.defn
class RiskMonitorWorkflow:
    """Monitor portfolio and close all if drawdown exceeds threshold"""

    @workflow.run
    async def run(self, max_drawdown_pct: float = 0.15):
        while True:
            portfolio = await workflow.execute_activity(
                get_portfolio,
                schedule_to_close_timeout=timedelta(seconds=30)
            )
            drawdown = portfolio.get("drawdown_pct", 0)
            if drawdown >= max_drawdown_pct:
                await workflow.execute_activity(
                    close_all_positions,
                    schedule_to_close_timeout=timedelta(minutes=2)
                )
                workflow.logger.warning(f"Drawdown {drawdown:.1%} — closed all positions")
                return
            # Check every 5 minutes
            await workflow.sleep(timedelta(minutes=5))

Workflow Patterns

Production-tested workflow designs for common financial agent use cases with Purple Flea.

📅

DCA Workflow

Buy a fixed dollar amount of any Purple Flea perpetual on a weekly or monthly schedule for N periods. Uses workflow.sleep() between executions — persisted across worker restarts, never misses a period, never double-buys.

Long-running
📉

Risk Monitor

A long-running loop that polls GET /portfolio every N minutes and calls close_all_positions if drawdown exceeds a configurable threshold. Runs indefinitely with Temporal — no server, no cron, no missed checks.

Real-time guard
🤝

Escrow Coordinator

Multi-step workflow: create_escrow → sleep until deadline → check_condition → branch to release_payment or dispute. Each step is idempotent — a crashed worker picks up exactly where it left off.

Trustless payments
🌐

Domain Portfolio Manager

Schedule domain renewals, monitor expiry dates, and automatically register new domains when conditions are met. Uses workflow.sleep() with precise timers instead of unreliable cron jobs.

Autonomous

Available Activities

Each Purple Flea API endpoint maps to a Temporal activity function. All activities support automatic retry with backoff.

Activity Function Description Purple Flea Endpoint
execute_trade(symbol, side, size_usd) Open a leveraged perpetual position. Returns position ID, entry price, liquidation price. POST /api/v1/trade
get_portfolio() Fetch all open positions with unrealized PnL, drawdown percentage, and total exposure. GET /api/v1/portfolio
close_all_positions() Market-close all open positions. Returns realized PnL and fees paid. POST /api/v1/trade/close-all
wallet_balance(chain) Get confirmed balance for a specific chain or all chains. Returns balance in native asset and USD equivalent. GET /api/v1/wallet/balance
casino_bet(game, amount_usd, params) Place a provably fair casino bet (crash, coin flip, dice, slots). Returns outcome and updated balance. POST /api/v1/casino/bet
create_escrow(amount_usd, counterparty, condition) Create a trustless escrow between two agent IDs. 1% fee on release; 15% referral on fees. POST /api/v1/escrow/create
release_escrow(escrow_id) Release escrowed funds to counterparty once condition is confirmed. Idempotent — safe to retry. POST /api/v1/escrow/release
register_domain(name) Register a crypto-native domain. Returns registration ID and expiry timestamp. POST /api/v1/domains/register

Fault Tolerance

How Temporal handles every failure mode in a production Purple Flea financial agent.

⏱️

Purple Flea API Timeouts

Set schedule_to_close_timeout on each activity. If the Purple Flea API doesn't respond within the window, Temporal marks the activity as failed and schedules a retry according to your RetryPolicy. Your workflow code never sees the timeout — it just awaits the next attempt.

🚦

Rate Limit Errors (HTTP 429)

Activity functions should raise_for_status() on every Purple Flea response. A 429 raises an exception, which Temporal catches and retries with configurable exponential backoff (e.g. backoff_coefficient=2.0, initial_interval=timedelta(seconds=5)). No manual sleep loops needed.

💥

Worker Process Crash

Temporal stores full workflow execution history server-side. If your worker process crashes mid-workflow, a new worker picks up the task from exactly the last successfully completed activity. No state is lost, no activities are re-run, and no positions are accidentally opened twice.

🌐

Partial API Failures

If execute_trade POSTs successfully to Purple Flea but the response is lost in transit (network failure after server ACK), Temporal's activity idempotency key ensures the activity is not retried with a new request. Include a client_request_id in your API body and Purple Flea will deduplicate on its end.

🔌

Temporal Server Downtime

If the Temporal server itself is unavailable, workers queue up pending activity results locally and flush them when the server reconnects. Long-sleep workflows (e.g. DCA sleeping 7 days) are unaffected — the timer is persisted in the Temporal service, not in your worker process.

Build reliable financial agents with Temporal + Purple Flea

Get a free API key and start wrapping Purple Flea calls in Temporal activities. Your trading workflows will be fault-tolerant, exactly-once, and capable of sleeping for months.