
Polsia’s Architecture: A Technical Teardown of “AI That Runs Your Company”
Polsia is the AI startup behind the pitch “AI that runs your company while you sleep.” It raised $30M at a $250M valuation in May 2026, run by a single founder with nine AI agents handling the operational load. The GitHub repo for the platform (github.com/PolsiaAI/Polsia) is public, which makes it possible to look past the pitch and see exactly what’s running underneath.
This post is a straight technical breakdown: the stack, the agents, the scheduling, and the infrastructure model. No verdict here on whether the product works, just what’s actually built.
System architecture
The stack is a fairly conventional web application shape, with the agent layer bolted on as a scheduled job system rather than a novel runtime.
┌─────────────────────────────────────────────────────────┐
│ nginx │
│ / → frontend /api/ → backend │
└────────────────┬────────────────────┬────────────────────┘
│ │
┌────────▼──────┐ ┌────────▼──────────┐
│ Next.js 14 │ │ FastAPI (Python) │
│ (frontend) │ │ + WebSocket │
└───────────────┘ └────────┬────────────┘
│
┌────────────────────────┼───────────────────┐
│ │ │
┌────────▼────────┐ ┌──────────▼──────┐ ┌────────▼──────┐
│ PostgreSQL 16 │ │ Redis + Celery │ │ ChromaDB │
│ (15 tables) │ │ (task queue) │ │ (vector mem) │
└─────────────────┘ └──────────────────┘ └───────────────┘
Nginx routes traffic between a Next.js 14 frontend and a FastAPI backend that also runs a WebSocket connection, presumably for the live activity feed shown on the dashboard. Postgres holds relational state across 15 tables. Redis and Celery form the task queue that drives the scheduled agent runs. ChromaDB sits alongside as a vector store, giving agents persistent memory across runs rather than starting from a blank context each cycle.
Nothing here is exotic. It’s the same shape you’d use for any multi-tenant SaaS with background jobs. The interesting part is what those background jobs actually do.
The nine agents
Each agent is a scheduled task, not a long-running process. They fire on a cadence, do their work, and exit.
| Agent | Responsibility | Schedule |
|---|---|---|
| Orchestrator | Writes morning plan + evening summary | 06:00 / 20:00 |
| Business Planning | Strategy, KPIs, growth recommendations | Daily |
| Competitor Research | Web search, profile updates | Daily |
| Social Media | Draft + post tweets | Every 2h |
| Email Outreach | Prospect finding + cold email sequences | Every 3h |
| Customer Support | Read inbox, draft replies | Every 3h |
| Ads Management | Google + Meta campaign optimization | Every 6h |
| Code Generation | Ship features, open PRs | On demand |
| Finance | Stripe revenue sync, spend tracking | Every 6h |
The Orchestrator is the coordination layer. It runs first thing in the morning to set the day’s plan and again in the evening to summarize what happened, and the other eight agents work against whatever state the Orchestrator leaves behind. There’s no continuous reasoning loop connecting the agents in real time; coordination happens through shared database state and Celery Beat’s schedule, not through agents talking to each other directly.
How agents actually call the model
This is the part worth pausing on. Per the repo’s own documentation, every agent calls Claude the same way: as a CLI subprocess.
claude -p "..." --output-format json
No API key. No SDK client. Each agent shells out to the Claude Code CLI binary, running in headless mode, and parses the JSON output. Authentication happens through OAuth tokens stored at ~/.claude on the host, mounted read-only into the containers. You run claude login once on the host machine, and every containerized agent inherits that session.
This is a legitimate way to get a lot of agentic capability without building a custom orchestration layer against the raw API, since the CLI already handles tool use, file access, and multi-step reasoning. It also means the agents’ capabilities are a direct function of whatever the Claude Code CLI exposes in headless mode, not a purpose-built agent framework. base_agent.py in the repo is the wrapper handling this subprocess call, and crew_factory.py holds the AGENT_MAP registry that maps each of the nine roles to its implementation.
Project layout
The codebase splits cleanly along the frontend/backend line, with the agent implementations sitting in their own directory:
polsia/
├── backend/
│ ├── app/
│ │ ├── agents/ # 9 agent implementations
│ │ │ ├── base_agent.py # call_claude() subprocess wrapper
│ │ │ ├── crew_factory.py # AGENT_MAP registry
│ │ │ ├── orchestrator/
│ │ │ ├── social_media/
│ │ │ ├── competitor_research/
│ │ │ ├── business_planning/
│ │ │ ├── email_outreach/
│ │ │ ├── customer_support/
│ │ │ ├── ads_management/
│ │ │ ├── code_generation/
│ │ │ └── finance/
│ │ ├── api/v1/ # REST endpoints + WebSocket
│ │ ├── core/ # DB, Redis, ChromaDB, security, retry
│ │ ├── models/ # SQLAlchemy ORM (15 tables)
│ │ ├── schemas/ # Pydantic request/response models
│ │ └── services/ # Business logic layer
│ ├── celery_app/ # Celery worker, Beat schedule, tasks
│ ├── alembic/ # Database migrations
│ └── tests/
│ ├── unit/ # SQLite in-memory, CLAUDE_CLI_MOCK=true
│ └── integration/ # Testcontainers (real Postgres + Redis)
├── frontend/
│ └── src/
│ ├── app/ # Next.js 14 pages (9 routes)
│ ├── components/ # ActivityFeed, MetricsCard, AgentStatusGrid, Sidebar
│ ├── hooks/ # useActivityFeed (WebSocket), useAgentStatus (polling)
│ └── lib/ # Typed API client
├── e2e/ # Playwright end-to-end tests
├── nginx/ # Reverse proxy config
└── scripts/ # init_db.sh, seed_company.py
Backend is Python (57% of the codebase per GitHub’s language breakdown), frontend is TypeScript (39.7%), with a thin layer of Dockerfile and Makefile glue holding it together.
Testing is set up sensibly: unit tests run against an in-memory SQLite database with CLAUDE_CLI_MOCK=true, which stubs out the CLI subprocess call entirely so the test suite doesn’t need live Claude credentials. Integration tests use Testcontainers to spin up real Postgres and Redis instances. All three GitHub Actions workflows (ci.yml, integration.yml, docker-build.yml) run with the mock flag, so CI never touches a real Claude session either.
Infrastructure and integrations
Running the stack locally is a standard Docker Compose flow:
git clone <repo>
cd polsia
cp .env.example .env
# Edit .env — set API_KEY and SANDBOX_MODE=true
docker-compose up -d
make init-db
SANDBOX_MODE=true is the default, and it matters: in sandbox mode, agents don’t make real posts, send real emails, or spend real ad money. Turning it off requires setting SANDBOX_MODE=false and filling in credentials for whichever integrations you want live: Twitter/X, SendGrid plus IMAP for email, Tavily for web search, Google Ads, Meta Ads, Stripe, and GitHub for the code generation agent’s pull requests.
That list is worth reading closely, because it’s the actual permission surface of the system. Once sandbox mode is off, the code generation agent can open pull requests against a connected GitHub repo, the ads agent can spend against connected Google and Meta accounts, and the finance agent can read Stripe revenue and track spend, all on a schedule, without a human clicking approve on each individual action.
What’s not in the repo
A few things worth naming precisely, since the public repo is the open-source self-hosted version of the agent stack, not necessarily the exact production system running polsia.com for paying customers:
- There’s no visible approval gate or human-in-the-loop checkpoint before an agent action executes, beyond the global sandbox toggle. It’s fully autonomous once live.
- The repo doesn’t show how production deployments provision hosting for end-user businesses (i.e., where a customer’s generated app actually gets deployed). That’s a separate concern from this self-hosted orchestration layer, and it’s the layer that determines who holds the keys to a given company’s infrastructure once it’s live.
- Rate limiting and spend caps beyond what Google Ads and Meta enforce natively aren’t part of this codebase as far as the public README documents.
None of that is unusual for an early-stage repo. It’s just the boundary of what “public and verifiable” actually covers here, versus what’s asserted in press coverage and demos.
The honest summary
Polsia’s architecture is a competent, fairly ordinary multi-service web app (Next.js, FastAPI, Postgres, Redis, Celery) with the actual “AI agent” work implemented as scheduled subprocess calls into the Claude Code CLI running headless. The novelty isn’t in the orchestration engineering, which is standard task-queue infrastructure. The novelty is in what the agents are pointed at: production infrastructure, live ad spend, and outbound customer communication, running on a clock instead of waiting for a human to hit send.
That’s a meaningful design choice, and it’s a reasonable one to build. Whether it’s a safe default to ship to paying customers with sandbox mode off is a separate question, and one the public repo doesn’t answer either way.
Source: github.com/PolsiaAI/Polsia, public README as of July 2026.

