Let’s use Supabase for this tutorial. You will need to create an account on Supabase. Run the below script in your Supabase SQL Editor.
-- Users tableCREATE TABLE users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email VARCHAR(255) UNIQUE NOT NULL, created_at TIMESTAMP DEFAULT NOW());-- Agents table CREATE TABLE agents ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name VARCHAR(255) NOT NULL, provider VARCHAR(50) NOT NULL, -- claude, codex, etc. instructions TEXT, runtime_id UUID, created_at TIMESTAMP DEFAULT NOW());-- Issues table (GitHub issues synced)CREATE TABLE issues ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), github_issue_id INTEGER, title TEXT NOT NULL, description TEXT, status VARCHAR(50) DEFAULT 'backlog', assignee_id UUID REFERENCES agents(id), created_at TIMESTAMP DEFAULT NOW());-- Agent tasks queueCREATE TABLE agent_task_queue ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), issue_id UUID REFERENCES issues(id), agent_id UUID REFERENCES agents(id), status VARCHAR(50) DEFAULT 'queued', -- queued, dispatched, running, completed, failed priority INTEGER DEFAULT 5, created_at TIMESTAMP DEFAULT NOW());-- Runtimes tableCREATE TABLE agent_runtimes ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name VARCHAR(255), provider VARCHAR(50), status VARCHAR(50) DEFAULT 'offline', last_heartbeat TIMESTAMP);
This is what you see after a successful run.
are these tables enough to create an agent? may be. Our goal is to setup minimal configuration to create an agent and run the agent in the background, inspired by the Multica’s architecture. You can learn more about Multica’s architecture on Deepwiki..
Create routes folder and add a file named agents.py in the routes folder.
from fastapi import APIRouter, HTTPExceptionfrom pydantic import BaseModelfrom database import get_dbrouter = APIRouter()class AgentCreate(BaseModel): name: str provider: str # claude, codex, etc. instructions: str = ""@router.post("/")async def create_agent(agent: AgentCreate): # Create agent in database # Return created agent pass@router.get("/")async def list_agents(): # Return all agents pass@router.get("/{agent_id}")async def get_agent(agent_id: str): # Return specific agent pass
routes/issues.py
Create a file named issues.py and add the below code
class IssueCreate(BaseModel): github_issue_id: int title: str description: str = ""@router.post("/")async def create_issue(issue: IssueCreate): # Create issue in database # Optionally sync with GitHub API pass@router.post("/{issue_id}/assign")async def assign_issue(issue_id: str, agent_id: str): # Assign issue to agent # Enqueue task for agent # This triggers the agent execution flow pass
routes/tasks.py
Create a file named tasks.py and add the following code
@router.get("/claim")async def claim_task(runtime_id: str): # Daemon calls this to claim next available task # Use FOR UPDATE SKIP LOCKED for concurrent safety pass@router.post("/{task_id}/start")async def start_task(task_id: str): # Mark task as running # Broadcast via WebSocket pass@router.post("/{task_id}/complete")async def complete_task(task_id: str, result: dict): # Mark task as completed # Update issue status if needed pass