Skip to main content
This guide is for developers who want a web service rather than a chat product. You will build a notes API with sign-in, per-user storage and a single-page front end, then deploy it. Prerequisites: CYCLS_API_KEY, and Docker if you want to run locally.

1. The smallest app

api.py
The decorated function returns an ASGI application. It runs inside the container at startup, so import heavy dependencies in the body rather than at module level.

2. Add sign-in

api.auth is a FastAPI dependency. A request without a valid token gets 401. Any OIDC provider works with cycls.JWT(jwks_url=...). See Authentication.

3. Add per-user storage

Storage needs a volume at /workspace.
api.workspace resolves the authenticated user’s own scope, so no route needs to filter by user id. Two users calling GET /notes see different data.

4. Bundle a front end

Put the HTML beside the Python file and copy it into the image.
The publishable key is resolved at request time, so the same HTML works locally and in production without a build step. The front end sends the token it gets from Clerk as Authorization: Bearer <token>.

5. Search with an inverted index

cycls.DB has no query language, so build the index you need. Prefix scans are the primitive.
Write the document and its index entries together:
These writes are not transactional. If the process dies between the document write and an index write, the index is incomplete. For a small app, rebuild the index on demand. For a larger one, write the document first and treat the index as derived state you can regenerate.

6. Run untrusted commands

cycls.Sandbox wraps bubblewrap with a read-only root, a cleared environment, and no network unless you enable it.
Only the caller’s own workspace is bound, so one user’s command cannot see another user’s files.

7. Deploy

App or agent

An agent is an app, so you can add routes to an agent with @my_agent.server.api_route(...) instead of deploying two services.

Next

Batch jobs

Fan work across instances with map.