Production-ready, multi-user AI agent platform for vision-grounded browser automation with per-user workspaces, LLM proxying, and Kubernetes deployment.
| Service | Description | Port (Dev) |
|---|---|---|
| Agent | FastAPI automation orchestrator with desktop_agent package |
39901 |
| Dashboard | Next.js web UI for session management | 13001 |
| Workspace | Chromium browser + Runtime API (K8s managed) | External |
| LLM Proxy | OpenRouter-compatible proxy with per-user usage tracking | 8001 |
| Tika | Apache Tika for document parsing | 9998 |
| Supabase | Auth, sessions, checkpoints, rules (external) | - |
-
Configure environment:
cp .env.example .env # Edit: SUPABASE_URL, SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY, OPENROUTER_API_KEY -
Start services:
docker compose up -d --build
-
Access services:
- Dashboard: http://localhost:13001
- Agent API: http://localhost:39901
- LLM Proxy: http://localhost:8001
- Tika: http://localhost:9998
- Workspaces: Managed via https://api.browser.kira.id
-
View logs:
docker compose logs -f agent-dev dashboard-dev llm-proxy
-
Configure:
cp .env.example .env # Set registry credentials: GITHUB_TOKEN, GITHUB_USERNAME # Set Supabase and OpenRouter keys
-
Build and push multi-arch images:
bash k8s/build-images.sh
-
Deploy:
./k8s/setup.sh # One-time: namespaces, secrets, RBAC ./k8s/deploy.sh # Deploy services
-
Verify:
kubectl get pods -n kira -w kubectl port-forward -n kira svc/dashboard 3000:3000
For better resource utilization, run browser pods on smaller worker nodes:
1. Setup Control Plane (first server):
# Install k3s on control plane (larger server)
curl -sfL https://get.k3s.io | sh -
# Get node token for workers
sudo cat /var/lib/rancher/k3s/server/node-token2. Add Worker Nodes (each smaller server):
# On each worker node, run:
./scripts/add-worker.sh <CONTROL_PLANE_IP> <NODE_TOKEN>
# Or manually:
curl -sfL https://get.k3s.io | K3S_URL=https://<CONTROL_PLANE_IP>:6443 \
K3S_TOKEN=<TOKEN> sh -3. Label Nodes (from control plane):
# Interactive labeling (recommended)
./scripts/label-nodes.sh
# Or manually label browser nodes
kubectl label nodes <worker-1> node-role=browser resource-tier=small
kubectl label nodes <worker-2> node-role=browser resource-tier=small
# Label control plane for core services
kubectl label nodes <control-plane> node-role=core resource-tier=large4. Deploy Platform:
# Build and push images
bash k8s/build-images.sh
# Setup and deploy
./k8s/setup.sh
./k8s/deploy.sh5. Verify Pod Placement:
# Check browser pods are on worker nodes
kubectl get pods -n kira-browsers -o wide
# Check core services on control plane
kubectl get pods -n kira -o wideRecommended Hetzner Setup:
- Control Plane: CPX31/CPX41 (4-8 vCPU, 8-16GB) for core services
- Workers: CX22/CX32 (2-4 vCPU, 4-8GB) for browser pods (~8-16 browsers per node)
See docs/MULTI_NODE_SETUP.md for complete guide and docs/MULTI_NODE_QUICK_REF.md for quick reference.
├── agent/ # FastAPI agent + desktop_agent library
├── dashboard/ # Next.js frontend
├── workspace/ # Chromium browser + Orchestration API
│ ├── browser/ # Custom Chromium image with Runtime API
│ └── orchestration/ # K8s browser lifecycle management
├── llm-proxy/ # LLM proxy with usage tracking
├── k8s/ # Kubernetes manifests and scripts
├── schema/ # Supabase database schema
└── tests/ # Integration tests
┌─────────────────────────────────────────────────────────┐
│ User Browser │
│ │ │
│ ┌─────▼─────┐ │
│ │ Dashboard │ (Next.js) │
│ └─────┬─────┘ │
│ │ │
│ ┌────────────┼────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌──────────┐ │
│ │ Agent │ │LLM Proxy│ │Workspace │ │
│ │(FastAPI)│ │ │ │(Chromium)│ │
│ └────┬────┘ └────┬────┘ └────┬─────┘ │
│ │ │ │ │
│ └────────────┼────────────┘ │
│ ▼ │
│ ┌──────────┐ │
│ │ Supabase │ │
│ │(Auth/DB) │ │
│ └──────────┘ │
└─────────────────────────────────────────────────────────┘
- Agent README - Desktop agent library and API with session management
- Dashboard README - Next.js frontend with queue UI features
- Workspace README - Browser orchestration platform
- LLM Proxy README - Usage tracking proxy
- K8s README - Kubernetes deployment guide
- Authentication Setup - Complete auth configuration guide
The platform supports multiple authentication methods via Supabase:
| Method | Description | Use Case |
|---|---|---|
| Email/Password | Traditional auth with email verification | Most users |
| Google OAuth | One-click Google sign-in | Quick onboarding |
| Anonymous | Guest access, convertible to permanent | Try before signup |
- Email/Password: Enabled by default in Supabase
- Google OAuth: Configure in Supabase Dashboard → Authentication → Providers → Google
- Anonymous: Enable in Supabase Dashboard → Authentication → Providers → Anonymous Sign-ins
- Configure SMTP for production emails (Settings → Authentication → SMTP)
- Set Site URL and Redirect URLs (Authentication → URL Configuration)
- Create Google OAuth credentials (Google Cloud Console)
- Enable Anonymous sign-ins if desired
- Customize email templates (Authentication → Email Templates)
See docs/AUTHENTICATION_SETUP.md for detailed setup instructions.
The platform uses a position-based queue for managing multi-step tasks. Items execute sequentially by position (0-indexed).
- Drag-and-Drop Reordering: Visual reordering in dashboard UI
- Inline Editing: Edit pending prompts without canceling
- Individual Deletion: Remove specific pending items
- Skip Current: Cancel executing task and advance to next
- Batch Operations: Add multiple prompts in one API call
# Create session with multiple tasks
curl -X POST https://api.kira.id/workspaces/{workspace_id}/sessions/messages \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"prompts": [
"Navigate to Google",
"Search for AI news",
"Click first result",
"Take screenshot"
]
}'
# Reorder: move position 3 to position 1
curl -X PATCH https://api.kira.id/workspaces/{workspace_id}/queue/reorder \
-H "Authorization: Bearer $TOKEN" \
-d '{"session_id": "...", "old_position": 3, "new_position": 1}'
# Edit prompt at position 2
curl -X PATCH https://api.kira.id/workspaces/{workspace_id}/queue/2 \
-H "Authorization: Bearer $TOKEN" \
-d '{"session_id": "...", "prompt": "Updated task"}'
# Delete position 3
curl -X DELETE https://api.kira.id/workspaces/{workspace_id}/queue/3?session_id=...
# Skip current task
curl -X POST https://api.kira.id/workspaces/{workspace_id}/cancel-current \
-d '{"session_id": "..."}'Rules:
- Only pending items (after current index) can be manipulated
- Current and completed items are immutable
- Positions auto-reindex after delete/reorder
- See Agent README for full API docs
The platform requires payment for all workspaces - there is no free tier. Users must subscribe to the Pro plan to create and use workspaces. Follow these steps to configure billing:
- Sign up at Stripe Dashboard
- Complete account verification and enable test mode for development
-
In Stripe Dashboard → Products, create one subscription product:
- Pro Plan: $19/month (3000 runtime minutes, 5M tokens, 10 workspaces)
-
Create a recurring monthly price for the product
-
Note the Price ID (e.g.,
price_1ABC...) from the pricing page
Note: There is no free tier - all workspaces require a paid subscription.
- In Stripe Dashboard → Settings → Billing → Customer Portal
- Click Activate to enable the billing portal
- Configure customer permissions:
- Allow customers to update payment methods
- Allow customers to view invoices
- (Optional) Allow subscription cancellation
- Copy the Configuration ID (starts with
bpc_) for better error messages
Note: The billing portal must be activated or customers will get errors when accessing their billing settings.
-
In Stripe Dashboard → Developers → Webhooks → Add endpoint
-
Set endpoint URL:
- Production:
https://your-domain.com/webhooks/stripe - Local dev: Use ngrok or localhost.run to expose localhost
- Production:
-
Select all of these events (required for full functionality):
Checkout Events:
checkout.session.completed- Initial subscription creation
Subscription Events (use wildcard or select individually):
customer.subscription.created- New subscriptioncustomer.subscription.updated- Plan changes, upgrades, downgradescustomer.subscription.deleted- Cancellationscustomer.subscription.paused- Paused subscriptionscustomer.subscription.resumed- Resumed subscriptions
Invoice Events:
invoice.paid- Successful paymentinvoice.payment_failed- Failed payment
💡 Tip: You can use
customer.subscription.*to listen to all subscription events at once. -
Copy the Webhook Signing Secret (starts with
whsec_) -
Test webhook delivery using Stripe's "Send test webhook" feature
Important:
- Webhook endpoint must be publicly accessible (HTTPS in production)
- The agent validates webhook signatures to prevent spoofing
- Monitor webhook delivery in Stripe Dashboard → Developers → Webhooks → [your endpoint]
Add to your .env file:
# Stripe Configuration
STRIPE_SECRET_KEY=sk_test_... # From Stripe Dashboard → Developers → API Keys
STRIPE_WEBHOOK_SECRET=whsec_... # From webhook configuration
STRIPE_BILLING_PORTAL_CONFIG_ID=bpc_... # (Optional) From billing portal settingsApply the database schema and migrations to Supabase:
Automated Migration (Recommended):
-
Install dependencies (for Node.js script):
cd schema npm install -
Configure environment:
# Copy and edit .env file cp .env.example .env # Add your database password (separate from service role key): # DB_PASSWORD=your-database-password-here
Note: The
SUPABASE_SERVICE_ROLE_KEYis for API access only. Database migrations require the actual PostgreSQL password from Supabase Dashboard > Settings > Database > Connection string. -
Run automated migration:
# Using Node.js (recommended) ./schema/apply_schema.js # Or using Python python schema/apply_schema.py # Or using Bash (requires psql) ./schema/apply_schema.sh
Manual Migration (Alternative):
-
Apply main schema:
-- In Supabase SQL Editor, copy/paste: -- schema/supabase_schema.sql (main tables, views, functions)
-
Apply migrations:
-- Apply in order: -- schema/migrations/002_billing_reconciliation_cron.sql (billing automation)
-
Configure Vault secrets (for billing reconciliation):
-- Agent API URL (adjust for your deployment) SELECT vault.create_secret('http://agent:8000', 'agent_api_url'); -- Service role key for API authentication SELECT vault.create_secret('your-service-role-key', 'reconcile_api_key');
-
Verify setup:
-- Check cron jobs SELECT * FROM v_cron_jobs; -- Test reconciliation SELECT trigger_billing_reconciliation();
See schema/migrations/README.md for detailed migration documentation.
- Start services:
docker compose up -d --build - Create a workspace via Dashboard (requires payment)
- Complete test payment with Stripe test card:
4242 4242 4242 4242 - Verify workspace becomes runnable after payment
- Use live mode API keys for production
- Webhook endpoint must be HTTPS
- Monitor webhook delivery in Stripe Dashboard
- Set up billing alerts and reconciliation jobs
For detailed billing architecture, see BILLING_SYSTEM.md.