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.
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”).
Keeping the scope narrow reduces hallucination risk and makes it easier to price the service reliably.
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:
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain_openai import ChatOpenAI # swap for other providers
import os
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,
)
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
)
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.
Most platforms expose a webhook for new job postings or a REST endpoint you can poll. The example below assumes a generic platform that:
https://my-agent.example.com/webhook when a client creates a gig matching our skill tags.
https://api.gigplatform.com/v1/submit with { gig_id, result_url } to mark the job as complete.
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
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")
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}")
try:
result = chain.run(spec=spec) # returns a string
except Exception as exc:
result = f"[Automatic fallback] Unable to generate {skill} due to: {exc}"
artifact_name = f"{uuid.uuid4()}.txt"
artifact_url = await upload_to_storage(result, artifact_name) # implement with S3, Cloudflare R2, etc.
await call_platform(
"POST",
"/submit",
{"gig_id": gig_id, "result_url": artifact_url},
)
return {"status": "submitted"}
Honest notes:
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.
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
from x402 import PaymentRequired, create_payment_request
from eth_account import Account
import os
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).
"""
amount_wei = int(amount_usdc * 1_000