Skip to main content
Real apps need credentials and durable storage. Capsule separates those into three primitives:
  • integrations for credentials that belong to the app user
  • secrets for credentials that belong to the workspace or app operator
  • filesystems for mounted durable files

1. Create workspace resources

capsule secret create OPENAI_API_KEY=sk-...
capsule fs create reports
Secrets and filesystems are workspace resources. The app opts into them in code.

2. Inject secrets and mount filesystems

app = cpsl.App(
    name="connected-app",
    image=cpsl.Image(python_packages=["openai"]),
    secrets=["OPENAI_API_KEY"],
    filesystems={"/data": cpsl.FileSystem("reports")},
)
Inside the runtime, /data behaves like a normal mounted directory.

3. Declare user integrations

Use integrations when the credential belongs to the signed-in app user.
app.add_integration(
    cpsl.GitHub(
        client_id=cpsl.Secret.from_name("GITHUB_CLIENT_ID"),
        client_secret=cpsl.Secret.from_name("GITHUB_CLIENT_SECRET"),
        scopes=["repo", "read:user"],
    )
)
Known secret-form integrations can be declared directly:
app.add_integration(cpsl.AWS())

4. Prompt at runtime

@app.message()
async def handle(session: cpsl.Session, msg: cpsl.Message):
    github = await session.require_integration(
        cpsl.Integration.GITHUB,
        reason="Connect GitHub so I can inspect repositories.",
    )
    await session.reply(f"Connected GitHub with scopes: {github.scopes}")
Use show_integration(...) instead when the connection is optional and you only want to render a non-blocking card.

5. Save files

with open("/data/report.txt", "w") as f:
    f.write("Generated by Capsule\n")
Use collections for queryable records and filesystems for durable files, generated artifacts, uploads, and large intermediate outputs.

Next steps