DEV Community

Nikhil Ranka
Nikhil Ranka

Posted on

From Prompt to Paycheck: Wiring an LLM Chain Into Real Gig Platforms

From Prompt to Paycheck: Wiring an LLM Chain Into Real Gig Platforms

Introduction

Building autonomous agents that can fetch work, execute it, and get paid requires more than just prompting a model. You need a deterministic pipeline that moves from natural‑language intent to concrete API calls, handles authentication, enforces pricing, and reports outcomes. This article walks through a minimal, production‑ready stack that connects an LLM chain to gig‑platform APIs and settles payments with the x402 standard. The goal is to show the moving parts, the trade‑offs you’ll encounter, and concrete code you can adapt — no hype, just engineering.

Architecture Overview

A typical agent consists of four loosely coupled layers:

  1. Intent parser – turns a user prompt into a structured task spec (e.g., “write a 500‑word blog post about React hooks”).
  2. LLM chain – runs the spec through a language model, possibly with tool use, retrieval, or self‑critique loops.
  3. Platform adaptor – translates the model’s output into the specific API calls required by a gig marketplace (Upwork, Fiverr, a custom job board, etc.).
  4. Payment & settlement layer – creates an x402 invoice, collects USDC on Base, and releases funds once the platform confirms completion.

Each layer communicates via JSON over HTTP, making the system easy to replace or scale independently.

LLM Chain Basics

We’ll use LangChain for its composable tool‑calling primitives, but the same ideas apply to any orchestrator. The chain has three stages:

  • PromptTemplate – defines the instruction and places the user request into a safe slot.
  • LLM – a hosted model (e.g., OpenAI GPT‑4‑turbo, Anthropic Claude 3, or an open‑weight model served via TGI).
  • Tools – optional functions the model can invoke, such as a web search or a calculator.
from langchain import LLMChain, PromptTemplate
from langchain.llms import OpenAI
from langchain.tools import Tool
import json, requests

# 1️⃣ Prompt
template = """You are a freelance assistant. Given the user request:
{request}
Produce a JSON spec with fields:
- title: short job title
- description: markdown description
- budget_usd: number (0.01–0.10)
- skills: list of strings
Return ONLY the JSON.
"""
prompt = PromptTemplate(input_variables=["request"], template=template)

# 2️⃣ LLM (swap for your provider)
llm = OpenAI(temperature=0.0, model_name="gpt-4-turbo")

# 3️⃣ Tool example: fetch market rates
def get_market_rate(_: str) -> str:
    r = requests.get("https://api.example.com/market-rate", params={"skill": "writing"})
    return json.dumps(r.json())

tools = [Tool(name="MarketRate", func=get_market_rate, description="Get average USD/word rate")]

chain = LLMChain(llm=llm, prompt=prompt, tools=tools)
Enter fullscreen mode Exit fullscreen mode

The chain returns a JSON string that the next layer can parse. Note the temperature set to 0.0 to reduce variability — critical when downstream APIs expect exact fields.

Gig Platform Adaptor

Most platforms expose a REST or GraphQL endpoint for creating a job/gig. The adaptor’s responsibilities are:

  • Validate the spec (required fields, budget limits).
  • Add platform‑specific headers (API key, OAuth token).
  • Map internal fields to the platform’s schema (e.g., titlejob_title).
  • Handle idempotency keys to avoid duplicate posts.

Below is a minimal adaptor for a hypothetical “GigHub” API that mirrors Upwork’s contract creation flow.

import os, uuid, httpx

GIGHUB_ENDPOINT = "https://api.gighub.com/v1/jobs"
API_KEY = os.getenv("GIGHUB_API_KEY")

def post_gig(spec: dict) -> dict:
    # Basic validation
    required = ["title", "description", "budget_usd", "skills"]
    for f in required:
        if f not in spec:
            raise ValueError(f"Missing field: {f}")
    if not (0.01 <= spec["budget_usd"] <= 0.10):
        raise ValueError("Budget out of allowed range")

    payload = {
        "job_title": spec["title"],
        "description": spec["description"],
        "budget": {
            "amount": spec["budget_usd"],
            "currency": "USD"
        },
        "skills": spec["skills"],
        "idempotency_key": str(uuid.uuid4())
    }

    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
        "Idempotency-Key": payload["idempotency_key"]
    }

    resp = httpx.post(GIGHUB_ENDPOINT, json=payload, headers=headers, timeout=10.0)
    resp.raise_for_status()
    return resp.json()   # contains job_id, status, etc.
Enter fullscreen mode Exit fullscreen mode

The adaptor throws on validation errors, allowing the orchestrator to retry with a revised spec or alert a human operator.

Payment Layer (x402)

x402 is a HTTP‑based micropayment protocol. The agent creates an invoice, the client pays USDC on Base, and the server releases the result only after verifying payment. The flow is:

  1. Invoice generation – returns a 402 response with a payment request (payment pointer, amount, asset).
  2. Client payment – the caller (or a relayer) sends the transaction to the payment pointer.
  3. Verification – the agent polls a smart‑contract or indexer to confirm receipt.
  4. Result delivery – if verified, return the gig output; otherwise, keep the 402.

Using the x402-py helper simplifies steps 1 and 3.

from x402 import create_invoice, verify_payment
import os

BASE_SEPOLIA_RPC = os.getenv("BASE_SEPOLIA_RPC")
PAYMENT_CONTRACT = os.getenv("X402_CONTRACT_ADDRESS")   # ERC‑20 USDC proxy

def request_payment(job_id: str, amount_usdc: float) -> dict:
    # amount_usdc is in USDC with 6 decimals (Base USDC)
    invoice = create_invoice(
        amount=int(amount_usdc * 1_000_000),   # convert to smallest unit
        asset="0x...",                         # USDC contract address on Base
        payer="",                              # left blank for payer to fill
        memo=f"Payment for gig {job_id}"
    )
    return invoice   # dict with fields: payment_request, expires_at, etc.

def check_paid(payment_request: str) -> bool:
    # verify_payment polls the contract until receipt or timeout
    return verify_payment(
        payment_request=payment_request,
        rpc_url=BASE_SEPOLIA_RPC,
        timeout_seconds=120
    )
Enter fullscreen mode Exit fullscreen mode

In practice you wrap request_payment in the HTTP handler that returns a 402 status, and check_paid in a background worker or a second endpoint that the client polls after submitting payment.

Honest Trade‑offs

Area Benefit Cost / Risk
Deterministic LLM output (temperature 0, strict JSON prompt) Reduces failed API calls, easier debugging May limit creativity; complex nuance can be lost
External tool use (market‑rate fetch) Keeps pricing aligned with real‑world data Adds latency, introduces third‑party failure points
Payment verification polling No need for websockets; simple HTTP Consumes agent uptime; payment confirmation can take 10‑30 s on Base
Platform‑specific adaptor Direct access to gig marketplace features Each platform requires its own mapper; maintenance overhead grows with number of

Top comments (0)