--- title: asa-api emoji: 🔎 colorFrom: yellow colorTo: indigo sdk: docker pinned: false license: mit --- # asa-api (Self-Hosted Docker + Tor) `asa-api` is a self-hosted Docker API + GUI wrapper around [`asa::run_task()`](https://github.com/cjerzak/asa-software). It uses: - `R` + `plumber` for HTTP endpoints - The `asa` package for orchestration (`run_task`, `run_task_batch`) - A lightweight password-protected browser GUI at `/` - A local Tor daemon for search/web egress inside the container ## What This Service Exposes 1. `GET /healthz` 2. `POST /v1/run` for a single prompt 3. `POST /v1/batch` for many prompts 4. `GET /` GUI page 5. `POST /gui/query` used by the GUI ## Security Model - API bearer auth is required for `/v1/*`: - Include `Authorization: Bearer 999` - GUI auth is password-based: - `/gui/query` checks `GUI_PASSWORD` ## Required Environment Variables Set these when running the container: - `GOOGLE_API_KEY` (or the provider key you use) - `GUI_PASSWORD` Optional secrets / vars: - `ASA_DEFAULT_BACKEND` (defaults to `gemini` if unset; examples: `openai`, `groq`, `anthropic`, `gemini`, `openrouter`) - `ASA_DEFAULT_MODEL` (example: `gemini-2.5-flash`) - `ASA_CONDA_ENV` (default: `asa_env`) - `ASA_USE_BROWSER_DEFAULT` (default: `false`, recommended for container stability) - `CORS_ALLOW_ORIGIN` (default: `*`) Provider-specific keys supported by `asa` include: - `OPENAI_API_KEY` - `GROQ_API_KEY` - `ANTHROPIC_API_KEY` - `GOOGLE_API_KEY` (or `GEMINI_API_KEY`) - `OPENROUTER_API_KEY` - Bedrock credentials if using `bedrock` ## API Usage ### 1) Health check ```bash curl -s http://localhost:7860/healthz ``` ### 2) Single query ```bash curl -s http://localhost:7860/v1/run \ -H "Content-Type: application/json" \ -H "Authorization: Bearer 999" \ -d '{ "prompt": "What is the population of Tokyo?", "config": { "backend": "gemini", "model": "gemini-2.5-flash" }, "run": { "output_format": "text", "recursion_limit": 20 } }' ``` ### 3) Structured JSON output ```bash curl -s http://localhost:7860/v1/run \ -H "Authorization: Bearer 999" \ -H "Content-Type: application/json" \ -d '{ "prompt": "Find Marie Curie birth year and nationality. Return JSON.", "run": { "output_format": "json" } }' ``` ### 4) Batch query ```bash curl -s http://localhost:7860/v1/batch \ -H "Authorization: Bearer 999" \ -H "Content-Type: application/json" \ -d '{ "prompts": [ "What is the capital of France?", "What is the capital of Japan?" ], "parallel": false, "run": { "output_format": "text" } }' ``` `/v1/batch` accepts only a plain JSON array of strings for `prompts`. Structured row objects that mirror upstream `asa::run_task_batch()` data-frame inputs are rejected by this adapter. ## Request Shape ### `POST /v1/run` ```json { "prompt": "string, required", "config": { "...": "any asa::asa_config argument" }, "run": { "...": "any asa::run_task argument except prompt/config/agent" }, "include_raw_output": false, "include_trace_json": false } ``` ### `POST /v1/batch` ```json { "prompts": ["required", "array", "of strings"], "config": { "...": "any asa::asa_config argument" }, "run": { "...": "batch-compatible shared options only; single-run-only keys are rejected" }, "batch": { "...": "any asa::run_task_batch argument except prompts/config/agent" }, "parallel": false, "include_raw_output": false, "include_trace_json": false } ``` ## Future Compatibility Strategy The adapter is intentionally resilient to `asa` changes: - It dynamically inspects `formals(asa::asa_config)`, `formals(asa::run_task)`, and `formals(asa::run_task_batch)`. - It only forwards request keys that exist in current function signatures. - For `/v1/batch`, it rejects single-run-only passthrough keys instead of silently dropping them. - This avoids hard crashes when upstream adds/removes optional args. ## GUI - Open `/` in your browser. - Enter `GUI_PASSWORD`. - Enter prompt and choose output format. - Leave `Use direct provider call (skip ASA)` unchecked to run the normal ASA agent flow. - Check `Use direct provider call (skip ASA)` to send the prompt straight to the configured provider/model without ASA search/tool orchestration. - Submit (Ctrl/Cmd + Enter is supported). Notes: - The checkbox is GUI-only; `/v1/run` and `/v1/batch` remain ASA endpoints. - The provider/model selection stays server-side and is not user-selectable in the GUI. ## Docker Build and Runtime The `Dockerfile` clones `asa-software` during build and installs `asa` from source. R dependency strategy in this image: - Base image is `rocker/r2u:24.04`. - Core R runtime packages (`plumber`, `jsonlite`, `reticulate`, `remotes`) are installed as binary apt packages (`r-cran-*`), not compiled from CRAN source. - This avoids source-compile failures such as `sodium` -> `plumber` install breaks. - The Docker build pre-creates `asa_env` with pinned `python=3.12.3` and `openssl=3.0.13` before calling `asa::build_backend()`, reducing rebuild drift that can break `reticulate` SSL imports on Ubuntu 24.04 / Hugging Face rebuilds. - Runtime linker guardrails are set so `reticulate` prefers conda environment libraries (`/opt/conda/envs/asa_env/lib` and `/opt/conda/lib`) to avoid C++ ABI loader mismatches. - Tor is installed in the image and started before the API. If Tor does not become ready, the container exits instead of serving direct search traffic. Build args: - `ASA_SOFTWARE_REPO` (default: `https://github.com/cjerzak/asa-software`) - `ASA_SOFTWARE_REF` (default: `main`) - `ASA_CONDA_PYTHON_VERSION` (default: `3.12.3`) - `ASA_CONDA_OPENSSL_VERSION` (default: `3.0.13`) Local build: ```bash docker build -t asa-api . ``` Local run: ```bash docker run --rm -p 7860:7860 \ -e GOOGLE_API_KEY=... \ -e GUI_PASSWORD=XXX \ asa-api ``` Then open: - `http://localhost:7860/healthz` - `http://localhost:7860/` ## Tor Deployment Defaults The container deploys Tor locally and exports these runtime defaults before starting `plumber`: - `ASA_PROXY=socks5h://127.0.0.1:9050` - `TOR_CONTROL_PORT=9051` - `ASA_TOR_CONTROL_COOKIE=/tmp/tor/control.authcookie` Tor scope is intentionally limited: - Search and webpage retrieval traffic uses Tor. - LLM provider API traffic remains direct, matching upstream `asa` behavior. - Browser/Selenium search remains disabled by default. Startup behavior is fail-closed: - Tor must answer a probe to `https://check.torproject.org/api/ip` with `IsTor=true`. - If the SOCKS proxy, ControlPort, or cookie setup never becomes ready, the container exits non-zero. `GET /healthz` now includes Tor readiness fields: - `tor_enabled` - `tor_ready` - `tor_proxy` - `tor_control_port` - `tor_cookie_present` - `tor_cookie_readable` You can override the local proxy defaults if needed: - `ASA_PROXY` - `TOR_CONTROL_PORT` - `ASA_TOR_CONTROL_COOKIE` - `ASA_TOR_PROBE_URL` - `ASA_TOR_STARTUP_TIMEOUT_SEC` ## Notes - Browser/Selenium tier is disabled by default (`use_browser = FALSE`) for better reliability in minimal containers. - If you want browser tier, set `config.use_browser = true` explicitly per request and ensure supporting binaries are installed. - If startup fails with Python import/linker errors (for example `CXXABI_1.3.15 not found`), inspect container logs and verify `GET /healthz` for `boot_error` details once the service is up.