From Prompt to Paycheck: Wiring an LLM Chain Into Real Gig Platforms
Building an autonomous AI agent that can actually earn money on a gig marketplace is less about flashy demos and more about plumbing together a few well‑understood pieces: a prompt‑driven LLM chain, a reliable API client for the platform, and a settlement mechanism that both you and the client trust. Below is a walk‑through of a minimal, production‑ish implementation that you can adapt to Upwork, Fiverr, or any platform that exposes a REST‑like job‑posting API.
1. Scope the Agent’s Capability
Before writing code, decide what the agent will actually do. Gig platforms reward clear, repeatable outcomes (e.g., “generate a 300‑word SEO blog post”, “convert a Figma frame to Tailwind CSS”, “write a unit test suite for a given function”).
- Input schema – a JSON object the agent receives from the platform webhook or a manual trigger.
- Output schema – the artifact the platform expects (plain text, a file URL, a diff patch).
- Failure handling – a deterministic fallback (e.g., return a generic template) or escalation to a human reviewer.
Keeping the scope narrow reduces hallucination risk and makes it easier to price the service reliably.
2. Choose an LLM Backend and Chain Framework
For most developers the quickest path is a managed LLM (OpenAI, Anthropic, or a self‑hosted Llama‑2 via Together.ai) combined with a lightweight orchestration library like LangChain or LlamaIndex. The chain we need is essentially:
- Prompt templating – inject the gig‑specific parameters into a stable instruction template.
- LLM call – retrieve a completion with controlled temperature and token limits.
- Post‑processing – strip markdown fences, validate length, optionally run a lint‑or‑spell check.
# agent_chain.py
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain_openai import ChatOpenAI # swap for other providers
import os
# 1️⃣ Prompt template – keep it short and deterministic
TEMPLATE = """
You are a freelance {role}.
Given the following specification, produce exactly {output_format}:
{spec}
Do not add any commentary outside the requested {output_format}.
""".strip()
prompt = PromptTemplate(
input_variables=["role", "output_format", "spec"],
template=TEMPLATE,
)
# 2️⃣ LLM – adjust max_tokens to match the gig’s price point
llm = ChatOpenAI(
model_name=os.getenv("OPENAI_MODEL", "gpt-4o-mini"),
temperature=0.2, # low temperature → repeatable output
max_tokens=800, # fits most short‑form gigs
)
# 3️⃣ Chain – reusable across gig types
def build_chain(role: str, output_format: str) -> LLMChain:
return LLMChain(llm=llm, prompt=prompt.partial(
role=role,
output_format=output_format,
))
Trade‑off: Using a managed API introduces a per‑call cost (≈$0.002–$0.01 for gpt‑4o‑mini) and a network dependency. If you need ultra‑low latency or want to avoid third‑party billing, swap ChatOpenAI for a locally served model (e.g., vllm or TensorRT‑LLM). Expect a 2‑5× increase in infrastructure complexity and a drop in raw token throughput unless you invest in GPU scaling.
3. Hook Into the Gig Platform
Most platforms expose a webhook for new job postings or a REST endpoint you can poll. The example below assumes a generic platform that:
- POSTs a JSON payload to
https://my-agent.example.com/webhookwhen a client creates a gig matching our skill tags. - Expects a POST to
https://api.gigplatform.com/v1/submitwith{ gig_id, result_url }to mark the job as complete.
# webhook_handler.py
from fastapi import FastAPI, Request, HTTPException
import httpx
import uuid
import os
from agent_chain import build_chain
app = FastAPI()
PLATFORM_API = os.getenv("GIG_PLATFORM_API", "https://api.gigplatform.com/v1")
PLATFORM_TOKEN = os.getenv("GIG_PLATFORM_TOKEN") # bearer token from platform dev console
# Pre‑build chains for the services we offer
BLOG_CHAIN = build_chain(role="SEO copywriter", output_format="plain text")
CSS_CHAIN = build_chain(role="frontend engineer", output_format="Tailwind CSS")
async def call_platform(method: str, path: str, json_data: dict | None = None):
async with httpx.AsyncClient() as client:
headers = {"Authorization": f"Bearer {PLATFORM_TOKEN}"}
resp = await client.request(
method,
f"{PLATFORM_API}{path}",
json=json_data,
headers=headers,
timeout=30.0,
)
if resp.status_code >= 300:
raise HTTPException(status_code=resp.status_code, detail=resp.text)
return resp.json()
@app.post("/webhook")
async def receive_gig(request: Request):
payload = await request.json()
gig_id = payload.get("gig_id")
spec = payload.get("description") # free‑form client brief
skill = payload.get("skill_tag") # e.g., "blog-writing" or "tailwind-css"
if not gig_id or not spec:
raise HTTPException(status_code=400, detail="Missing gig_id or description")
# 1️⃣ Pick the right chain
chain = BLOG_CHAIN if skill == "blog-writing" else CSS_CHAIN if skill == "tailwind-css" else None
if not chain:
raise HTTPException(status_code=400, detail=f"Unsupported skill: {skill}")
# 2️⃣ Run the LLM
try:
result = chain.run(spec=spec) # returns a string
except Exception as exc:
# Log and fall back to a safe generic answer
result = f"[Automatic fallback] Unable to generate {skill} due to: {exc}"
# 3️⃣ Persist the artifact (here we use a temporary public bucket)
artifact_name = f"{uuid.uuid4()}.txt"
artifact_url = await upload_to_storage(result, artifact_name) # implement with S3, Cloudflare R2, etc.
# 4️⃣ Notify the platform the work is done
await call_platform(
"POST",
"/submit",
{"gig_id": gig_id, "result_url": artifact_url},
)
return {"status": "submitted"}
Honest notes:
- Rate limits – Both the LLM provider and the gig platform will throttle you. Implement exponential back‑off and a queue (e.g., Redis + RQ) to smooth bursts.
- Authentication – Platform tokens often have short lifespans; store them in a secret manager and refresh via OAuth refresh token flow when needed.
- File handling – Never write large binaries to the container’s volatile filesystem. Use object storage with a public‑read signed URL that expires after a reasonable window (e.g., 1 hour).
4. Settlement: Getting Paid in USDC on Base
The original prompt asked for a paycheck. The most straightforward way to earn programmatically is to attach a micropayment to each completed gig using the x402 protocol (HTTP 402 Payment Required) and settle in USDC on the Base L2.
- Create a payment‑gated endpoint – instead of directly posting the result URL, the agent returns an x402 challenge that includes a payment request (amount, asset, payee address).
- Client (the platform or a front‑end) pays – the payer signs the transaction with their wallet; the agent validates the receipt on‑chain before releasing the artifact.
- Reconcile – a simple off‑chain watcher confirms the payment and marks the gig as “paid” in your internal ledger.
Below is a minimal x402 responder built on top of the previous webhook. It uses the x402 Python package (a thin wrapper around ethers.js‑style signing).
python
# x402_payment.py
from x402 import PaymentRequired, create_payment_request
from eth_account import Account
import os
# Agent’s wallet – fund it with a small USDC balance on Base
AGENT_PRIVATE_KEY = os.getenv("AGENT_PRIVATE_KEY")
AGENT_ADDRESS = Account.from_key(AGENT_PRIVATE_KEY).address
USDC_CONTRACT_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" # USDC on Base (mainnet)
BASE_RPC = os.getenv("BASE_RPC", "https://mainnet.base.org")
def payment_challenge(amount_usdc: float) -> dict:
"""
Returns an x402 payload the client must satisfy.
amount_usdc is in decimal USDC (e.g., 0.02 for $0.02).
"""
# Convert to the smallest unit (USDC has 6 decimals)
amount_wei = int(amount_usdc * 1_000
Top comments (0)