# floom - Complete Reference for AI Agents > Turn Python functions into web apps. Type hints become the UI, API, and shareable links. Self-hosted with Docker. Open source (MIT). ## Overview floom bridges the gap between writing a Python function and having it running as a usable web application. It extracts type hints, generates an OpenAPI schema, creates a web form UI, runs code in a Docker sandbox, and produces a shareable link. Self-hosted with a single Docker command. No cloud account required. ## Installation ### Docker (recommended) ```bash docker run -p 3000:3000 -p 3001:3001 \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /tmp/floom-workspaces:/tmp/floom-workspaces \ -v /tmp/floom-storage:/tmp/floom-storage \ -v floom-data:/data \ ghcr.io/floomhq/floom ``` Web UI on port 3000, API on port 3001. ### From source ```bash git clone https://github.com/floomhq/floom cd floom npm run setup:local docker-compose up --build ``` ### CLI ```bash npm install -g @floomhq/cli floom deploy my-app.py --name "My App" floom run greet name=world ``` ### MCP Server (for Claude, Cursor, and other AI agents) ```bash npx @floomhq/cli setup-mcp ``` This prints a config block to paste into your MCP settings. Gives agents tools to deploy, run, list, and manage floom apps. ## Python SDK ### Basic action ```python from floom import app @app.action def greet(name: str) -> dict: return {"message": f"Hello, {name}!"} ``` ### With persistent memory ```python from floom import app, remember, forget @app.action def count_visits(name: str) -> dict: visits = (remember("visits") or 0) + 1 remember("visits", visits) return {"message": f"Hello {name}! Visit #{visits}"} # remember(key, value) -> set # remember(key) -> get # forget(key) -> delete ``` ### Full storage API ```python from floom import app, storage @app.action def configure(theme: str = "dark") -> dict: storage.set("config", {"theme": theme}) return storage.get("config") # storage.set(key, value) # storage.get(key, default=None) # storage.list() -> list of keys # storage.delete(key) ``` ### SQLite database ```python from floom import app, db, get_db @app.action def add_item(name: str) -> dict: db.execute("CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY, name TEXT)") db.execute("INSERT INTO items (name) VALUES (?)", (name,)) rows = db.execute("SELECT * FROM items").fetchall() return {"items": [dict(r) for r in rows]} ``` ### File outputs (artifacts) ```python from floom import app, save_artifact, save_dataframe, save_json @app.action def generate_report(query: str) -> dict: save_artifact("report.html", "

Report

") save_json("data.json", {"query": query, "results": []}) return {"status": "report generated"} ``` ### Secrets ```python from floom import app, context @app.action def fetch_data(query: str) -> dict: api_key = context.get_secret("MY_API_KEY") # use api_key to call external service return {"result": "..."} ``` ### Scheduled execution ```python from floom import app @app.schedule("0 9 * * *", timezone="UTC") @app.action def daily_report() -> dict: return {"summary": "Daily report generated"} ``` ### Custom action names ```python @app.action(name="custom_name") def my_func(y: str) -> dict: return {"greeting": f"Hello, {y}!"} ``` ### Type hints -> UI mapping | Python type | Generated UI | Notes | |-------------|-------------|-------| | `str` | Text input | | | `int` | Number input | | | `float` | Number input (decimal) | | | `bool` | Checkbox | | | `Literal["a","b","c"]` | Dropdown select | Import from typing | | `dict` | JSON editor | | | Default values | Pre-filled placeholders | e.g. `city: str = "Berlin"` | | Return `dict` | Structured output card | Always return dict | ## REST API Reference Base URL: `http://localhost:3001` (self-hosted) or `https://floom.dev` (demo) ### Per-app API (agent-friendly, no IDs needed) ```bash # Discover what an app can do GET /v1/apps/{slug} # Returns: actions list with input schemas # Call an action (synchronous, returns result directly) POST /v1/apps/{slug}/{action_name} Content-Type: application/json Body: { "param1": "value1", "param2": "value2" } # Returns: {"status":"success","result":{...},"duration_ms":1200} ``` ### Project management ```bash # List all apps GET /v1/projects # Create a new app POST /v1/projects Body: {"name": "my-app", "code": "...python code..."} # Get app details GET /v1/projects/{id} # Update app metadata (name, slug only; to update code, redeploy) PATCH /v1/projects/{id} Body: {"name": "new-name", "slug": "new-slug"} # Delete app DELETE /v1/projects/{id} ``` ### Deployment ```bash # Deploy (build and start) POST /v1/projects/{id}/deploy # Check deploy status GET /v1/projects/{id}/deploy/status ``` ### Execution ```bash # Run an action POST /v1/runs Body: {"project_id": "...", "endpoint_id": "...", "input": {...}} # Get run result GET /v1/runs/{run_id} ``` ### Secrets (encrypted at rest) ```bash # Set a secret (one at a time) POST /v1/projects/{id}/secrets Body: {"key": "API_KEY", "value": "sk-..."} # List secret names (values hidden) GET /v1/projects/{id}/secrets ``` ### Storage ```bash # List storage keys GET /v1/projects/{id}/storage # Get a value GET /v1/projects/{id}/storage/{key} # Set a value PUT /v1/projects/{id}/storage/{key} Body: {"value": {...}} ``` ### Templates ```bash # List available templates GET /v1/templates # Create app from template POST /v1/templates/{template_id}/create ``` ### OpenAPI spec ```bash GET /v1/openapi.json ``` Full OpenAPI 3.0.3 schema describing all endpoints, request/response types, and authentication. ## CLI Reference ```bash floom deploy --name "App Name" # Deploy a Python file floom run key=value # Execute an action floom list # List all apps floom logs # View execution logs floom doctor # Check local setup floom storage list # List storage keys floom storage get # Get a value floom storage set # Set a value floom share create # Create a shareable link floom setup-mcp # Configure MCP for AI agents ``` ## MCP Tools (complete list, 32 tools) When the MCP server is configured, agents get these tools: ### Core Workflow - `deploy` - Deploy Python code, returns project ID and endpoint list - `run` - Execute an action by slug+action or project_id+endpoint_id - `list_projects` - List all deployed apps - `get_project` - Get app details and endpoint schemas - `delete_project` - Remove a project - `update_project` - Update project name or slug ### Version Management - `list_versions` - See all versions of a project with hashes - `promote` - Promote a version to production with health check - `rollback` - Roll back to a previous version ### Storage (persistent key-value) - `storage_set` - Store a value (up to 10MB) - `storage_get` - Retrieve a value by key - `storage_delete` - Remove a key - `storage_list` - List all keys for a project ### Secrets - `manage_secrets` - Set, list, or delete encrypted API keys (action param) ### Sharing - `create_share_link` - Generate a public URL - `list_share_links` - List existing links - `disable_share_link` - Revoke a share link ### Context (project metadata) - `fetch_context` - Pull context from a URL - `get_context` - Get a stored context - `list_contexts` - List all contexts - `delete_context` - Remove a context - `refresh_context` - Re-fetch a context from its URL ### Scheduling - `create_schedule` - Set up cron-based execution - `list_schedules` - List schedules for a project - `delete_schedule` - Remove a schedule ### Templates - `list_templates` - Browse starter templates - `get_template` - Get template details and code - `create_from_template` - Create a project from a template ### GitHub - `deploy_from_github` - Deploy directly from a GitHub repo URL ### Webhooks - `enable_webhooks` - Enable inbound webhook triggers - `disable_webhooks` - Disable webhooks ### Logs - `get_logs` - View execution logs with error details and suggested fixes ## Agent Cookbook ### Pattern 1: Deploy from chat Write code, deploy, get a URL back: ``` 1. deploy(code="from floom import app\n\n@app.action\ndef greet(name: str) -> dict:\n return {\"message\": f\"Hello, {name}!\"}", name="greeter") -> Returns: {project_id, slug: "greeter", endpoints: [{id, name: "greet", path: "/greet"}]} 2. run(app_slug="greeter", action="greet", json={"name": "world"}) -> Returns: {"message": "Hello, world!"} 3. create_share_link(project_id="...") -> Returns: {url: "https://floom.dev/s/abc123"} ``` ### Pattern 2: Stateful tool with remember() Deploy an app that persists data across runs: ```python from floom import app, remember @app.action def add_note(text: str) -> dict: notes = remember("notes") or [] notes.append(text) remember("notes", notes) return {"notes": notes, "count": len(notes)} @app.action def get_notes() -> dict: return {"notes": remember("notes") or []} ``` After deploying, use MCP storage tools to inspect state: ``` storage_list(project_id="...") -> ["notes"] storage_get(project_id="...", key="notes") -> ["first note", "second note"] ``` ### Pattern 3: Multi-action API with secrets ```python from floom import app, context @app.action def search(query: str, max_results: int = 5) -> dict: api_key = context.get_secret("SEARCH_API_KEY") # use api_key to call search API return {"results": [...]} @app.action def summarize(text: str) -> dict: api_key = context.get_secret("LLM_API_KEY") # use api_key to call LLM return {"summary": "..."} ``` Set secrets before first run: ``` manage_secrets(project_id="...", action="set", key="SEARCH_API_KEY", value="sk-...") manage_secrets(project_id="...", action="set", key="LLM_API_KEY", value="sk-...") ``` IMPORTANT: Deploy with network enabled since this calls external APIs: ``` deploy(code="...", name="search-tool", config={"network": true}) ``` ### Pattern 4: File processing pipeline ```python from floom import app, save_artifact, save_dataframe import pandas as pd @app.action def analyze_csv(data: str, include_nulls: bool = False) -> dict: df = pd.read_csv(pd.io.common.StringIO(data)) if not include_nulls: df = df.dropna() save_dataframe(df, "cleaned.csv") save_artifact("stats.html", df.describe().to_html()) return {"rows": len(df), "columns": list(df.columns)} ``` Deploy with requirements: ``` deploy(code="...", name="csv-analyzer", requirements=["pandas"]) ``` ### Pattern 5: Deploy from GitHub One call to deploy a repo: ``` deploy_from_github(github_url="https://github.com/user/my-tool", name="my-tool") ``` With a specific branch or tag: ``` deploy_from_github(github_url="https://github.com/user/my-tool", name="my-tool", github_ref="v2.0") ``` Repo must contain `main.py` with `@app.action`. Optional: `requirements.txt`, `floom.yaml`. ### Pattern 6: Version management Safe update workflow: ``` 1. deploy(code=updated_code, name="my-app") -> Creates new version automatically 2. run(app_slug="my-app", action="test", json={...}) -> Test the new version 3a. If broken: rollback(project_id="...") -> Reverts to previous version 3b. If working: promote(project_id="...", version_id="...") -> Locks this version as production 4. list_versions(project_id="...") -> See all versions with status ``` ## floom.yaml Configuration (optional) Pass as `config` parameter in deploy(): ```yaml endpoints: generate: description: "Generate a report" timeout_seconds: 120 lane: cpu # cpu or gpu inputs: query: {type: string} secrets: ["API_KEY", "DB_URL"] # declare required secrets network: true # enable outbound network (default: false) dependencies: ["requests", "pandas"] ``` IMPORTANT: network defaults to false (--network none in Docker). If your function calls external APIs (requests.get, urllib, httpx), you MUST set network: true. ## Deploy Status Workflow After deploy(), status transitions: draft -> deploying -> live (or failed). Via MCP: 1. `deploy(code, name)` -> returns immediately with project_id 2. `get_project(project_id)` -> check status field 3. If "deploying", wait 2-3 seconds, check again 4. If "live", proceed to run() 5. If "failed", read error.message + error.suggested_fix, fix code, redeploy Via REST: ``` GET /v1/projects/{id}/deploy/status -> {"status": "live"|"deploying"|"failed"} ``` ## Debugging a Failed Run 1. `get_logs(project_id)` -> read print() output + tracebacks 2. If ImportError -> add missing package to requirements, redeploy 3. If "secret not found" -> `manage_secrets(project_id, action="set", key="KEY_NAME", value="...")` 4. If timeout -> increase timeout_seconds in run(), or optimize function 5. If network error -> set config.network: true, redeploy 6. Fix code -> `deploy(fixed_code, name)` -> redeploy (creates new version) 7. Re-run and verify ## Error Handling Deploy errors: Check `status` field. If "failed", read `error.message` and `error.suggested_fix`. Run timeouts: Default 60s. Pass timeout_seconds to extend (max 300s). If timeout, retry with longer timeout or simplify the function. Rate limits: 429 response. Wait 60 seconds, retry. Authenticated requests get 120/min, anonymous get 60/min. Missing secrets: Run returns error with "secret X not found". Use manage_secrets to set it, then re-run. Network disabled: Function tries to reach internet but fails silently. Set config.network: true in deploy. Import error: Package not installed. Add to requirements array in deploy(). Storage full: 10MB per value, 100MB per project. Delete old keys with storage_delete. Resource limits (defaults): - RAM: 512MB per container (RUNNER_MEMORY env var) - CPU: 1 core per container (RUNNER_CPUS env var) - Timeout: 60 seconds per run (max 300s) - Network: disabled by default (--network none) ## Architecture ``` Python function (type hints) -> OpenAPI schema extraction -> Auto-generated web form -> Docker sandbox execution -> Shareable link Stack: - Frontend: Next.js (TypeScript) - API: Hono.js (TypeScript) - Runtime: Python 3.11 in Docker - Database: SQLite (self-hosted) or PostgreSQL via Supabase (cloud) - Secrets: AES-256-GCM envelope encryption - Sandbox: Docker with --network none, --cap-drop ALL ``` ## Environment Variables | Variable | Default | Description | |----------|---------|-------------| | MASTER_ENCRYPTION_KEY | auto-generated | 32-byte base64 key for secrets | | COMPUTE_BACKEND | docker | Execution backend | | PORT | 3001 | API server port | | API_KEY | (none) | Bearer token for API auth | | RUNNER_IMAGE | floom-runner:latest | Docker image for execution | | RUNNER_MEMORY | 512m | Memory limit per container | | RUNNER_CPUS | 1 | CPU limit per container | | RUNNER_NETWORK | none | Network mode (none for isolation) | | GEMINI_API_KEY | (none) | Enables AI smart ingest for raw scripts | ## Comparison with alternatives | Feature | floom | FastAPI | Streamlit | Gradio | |---------|-------|---------|-----------|--------| | Auto UI from code | Yes (type hints) | No | Manual widgets | Manual components | | Zero config deploy | Yes (Docker) | Manual | Streamlit Cloud | Hugging Face Spaces | | Sandboxed execution | Yes (Docker) | No | No | No | | Shareable links | Built-in | Manual | Built-in | Built-in | | Persistent storage | Built-in (remember()) | Manual | Session state | Manual | | REST API | Auto-generated | Manual (but excellent) | No | API mode | | MCP integration | Built-in (32 tools) | No | No | No | | Self-hosted | Yes | Yes | Yes | Yes | | Open source | MIT | MIT | Apache 2.0 | Apache 2.0 | floom is not a replacement for FastAPI (which is excellent for building production APIs). floom is for when you have a Python function and want it live as a usable app in under a minute, with no frontend work. ## Links - Website: https://floom.dev - GitHub: https://github.com/floomhq/floom - PyPI: https://pypi.org/project/floom/ - npm CLI: https://www.npmjs.com/package/@floomhq/cli - MCP Server: https://www.npmjs.com/package/@floomhq/mcp-server - OpenAPI spec: https://floom.dev/v1/openapi.json - Docker image: ghcr.io/floomhq/floom - Agent workflow guide: https://github.com/floomhq/floom/blob/main/docs/AGENT_GUIDE.md