Skip to content

lamia-cloud

Run Lamia scripts in the cloud with the same .lm workflow you use locally.

lamia-cloud currently supports GCP and gives you:

  • one-time cloud execution with --remote
  • cloud scheduling with Cloud Scheduler
  • Cloud Run Job execution with logs in Cloud Logging
  • event-driven triggers (see Triggers)

Installation

pip install "lamia-lang[cloud]"

Configuration

Add a cloud section to your project's config.yaml:

cloud:
  provider: gcp
  project_id: my-gcp-project
  location: us-central1
Field Required Description
provider yes Cloud provider (gcp)
project_id yes Your GCP project ID
location yes Region for scheduling and execution (e.g. us-central1)
resources.task_timeout_seconds no Cloud Run Job task timeout in seconds. Default 3600 (1h), max 604800 (7 days). Increase for long-running jobs.

Authentication

lamia-cloud uses Application Default Credentials. Authenticate once:

gcloud auth application-default login

One-time Cloud Run (--remote)

lamia my_script.lm --remote

Use this first to validate cloud permissions, runtime behavior, and logs before creating a schedule.

Why it can take a while to start: each run waits for the cloud platform to schedule and provision an instance for the job before your script starts. In our own testing this has taken anywhere from 60-130 seconds, on top of a few seconds for the interpreter itself to start once the container is running. --remote prints the breakdown so you can see the split, e.g.:

Completed in 100.4s (pending 83.1s, execution 17.3s)

pending is the wait for GCP to schedule and start your container; execution is your script actually running. You're only billed for execution time, not pending.

Cloud Scheduling

lamia schedule add daily_task.lm --every day --remote

This uses the same cloud runtime as one-time --remote execution.

All other commands work transparently:

lamia schedule list          # shows both local and cloud jobs
lamia schedule update <id> --cron "0 12 * * *"
lamia schedule remove <id>   # tears down the cloud job + scheduler job

How It Works

  1. lamia <script>.lm --remote packages your project and deploys a Cloud Run Job
  2. Your script runs via the lamia CLI inside the job container (same script semantics as local)
  3. lamia schedule add --remote creates a Cloud Scheduler trigger for that job
  4. Logs (stdout/stderr) go to Cloud Logging under Cloud Run Job execution logs
  5. Exit status is reported back to the local lamia registry so lamia schedule list shows it

Version: A cloud script is built with the newest version of Lamia at the time you deploy it, and it keeps that version until it's rebuilt. Deploying again after you change your script rebuilds it with the latest version. Updates stay compatible with your existing scripts, so cloud runs behave the same as running on your computer.

Logs

View execution logs:

lamia schedule logs <id>

Or directly in GCP Console under Cloud Run > Jobs > lamia-... > Executions > Logs.

API Enablement

lamia-cloud automatically enables required APIs on first use. No manual gcloud services enable step is needed.

Vertex AI model access

API enablement is separate from Vertex AI's per-model access grant. The first time a project calls a gated publisher model (for example, Anthropic's Claude models) through Vertex AI, Google requires one-time per-project consent, granted from that model's Model Garden page (found under Google Cloud Console's Agent Platform section) — this isn't an API flag, so lamia-cloud cannot complete it on your behalf.

Before any build or deploy, --remote checks every model in your model_chain against Vertex in one batch and, if any are missing access, reports all of them together with a Model Garden link and a search name for each (e.g. claude-sonnet-4-5-20250929 → search "Claude Sonnet 4.5"). If a run reports missing models, open the printed link, search each name in Model Garden, and click Enable on its card, then retry.

Secrets for Cloud Execution

.env files are never copied into the deployed container, so a script that reads a key from the environment finds nothing in the cloud until you name that key. List the ones your script needs under cloud.secrets:

cloud:
  provider: gcp
  project_id: my-gcp-project
  location: us-central1
  secrets:
    - THIRD_PARTY_API_KEY

Leave the values where they already are — your project's .env — and deploy:

lamia my_script.lm --remote

Each listed key is written to Secret Manager, and the Cloud Run Job is given a reference to it rather than the value. GCP injects it as an environment variable when the job runs, so os.environ["THIRD_PARTY_API_KEY"] works exactly as it does locally, and the value never appears in the job's configuration.

Nothing outside that list leaves your machine. Model provider keys get no special treatment — an unlisted key is simply missing at runtime, whatever it is. Note that you should not add API keys for built-in models to the cloud.secrets list, as they authenticate through Vertex AI.

Cleanup

Removing a schedule or trigger deletes the secrets it was using:

lamia schedule remove <id>
lamia trigger clear <id>

A secret shared by several deployments survives until the last one referencing it is gone, so removing one of two schedules that use the same key leaves the key in place.

Editing a value in .env does not reach a running deployment on its own — deploy again to push the new value.

CI/CD environments

In CI, there is no .env file. Lamia resolves secret values from the process environment (os.getenv), so any key listed in cloud.secrets that is available as an environment variable will be picked up. For step-by-step setup, see Git-Based Deployment.

File Sync for Cloud Execution

When your script uses with files(...) to provide context to the LLM, Lamia automatically uploads the referenced files to cloud storage (GCS) so the script runs identically in the cloud.

What gets uploaded

Only the folders and files specified in with files(...) syntax are uploaded. Nothing else.

with files("./docs", "./data/input.csv"):
    def summarize():
        "Summarize {@report.pdf} and {@input.csv}"

In this example, every file inside ./docs/ and the single file ./data/input.csv are synced to cloud storage.

How it works at runtime

When files are synced, the GCS bucket is mounted as the container's working directory. All relative file paths in your script resolve directly into the mounted bucket. Reads pull from the bucket, writes go to the bucket.

Persistence and cleanup

Files written during cloud execution are not deleted when the job finishes — they remain in GCS until removed manually.

  • A scheduled script that appends to a CSV on each run accumulates data across runs.
  • A one-time --remote run that writes output.txt leaves that file in the bucket after completion.
  • Re-running the same script sees files from previous runs.
  • Trigger stages can read files written by earlier stages of the same trigger.

Each script's files are stored under a namespace subdirectory in the bucket. lamia schedule list and lamia trigger list show that namespace for any script with file-write operations.

To inspect or remove stored files directly:

# List everything stored for this project
gsutil ls gs://<project-id>/

# Remove one script's files (namespace from `schedule list` / `trigger list`)
gsutil -m rm -r gs://<project-id>/<namespace>/

# Remove everything
gsutil -m rm -r gs://<project-id>/**

Your project ID is in config.yaml under cloud.project_id.

Incremental sync

Lamia tracks file checksums. On subsequent deploys, only changed or new files are uploaded. Files already in the bucket with matching content are skipped. This keeps re-deploy times fast.

When multiple team members sync the same project, Lamia issues a warning before overwriting files that have been modified by someone else.

Security considerations

All files in with files(...) directories are uploaded recursively. This includes every file in the folder — Lamia uploads everything so the LLM context resolution works exactly as on your local machine.

Risks to be aware of:

  1. Secrets — Lamia scans for common secret file patterns (.env, files containing API_KEY, private key, etc.) and blocks the upload with a clear error. Nevertheless, review what's in your directories before deploying.

  2. Security surface — Every file you upload exists in cloud storage. Fewer files = smaller attack surface. Only upload what the script actually needs.

  3. Sync speed — Larger directories mean more files to check and upload on every script update. Every time you modify your script, Lamia must scan the referenced directories and sync changes. Hundreds of large files slow this down.

  4. Storage and bandwidth cost — GCS storage is cheap (~$0.02/GB/month for Standard), but bandwidth adds up with large syncs. For typical Lamia usage (documents, configs, CSVs), costs are negligible — a few cents per month. If you're syncing gigabytes of data, consider limiting scope.

Best practices

Practice Why
Create a dedicated folder for your script's data (e.g., ./context/) Keeps scope clear, fast sync, no surprise files
Avoid pointing with files(...) at ~/Documents or home directories Personal files, secrets, irrelevant data — all gets uploaded
Use relative paths from the project root Portable across machines and team members
Keep referenced directories small and focused Faster sync, lower cost, better LLM context quality

It is not terrible to reference a larger directory — Lamia handles it correctly and securely. The practical concern is that LLMs can get lost in large file sets (context dilution), sync gets slower, and the security surface grows. If your workflow genuinely needs many files, it works — just understand the tradeoffs.


Gitflow for Lamia (Team Workflows)

When multiple developers work on a shared Lamia project, file paths must be consistent across machines. The recommended approach: use paths relative to the Git repository root.

The problem with absolute paths

# BAD for teams — breaks on other machines
with files("~/Documents/company_data/"):
    def analyze():
        "Summarize {@quarterly_report.pdf}"

This works for one developer but fails for everyone else (different home directory, different folder structure).

The solution: repository-relative paths

# GOOD for teams — works for everyone who clones the repo
with files("./data/"):
    def analyze():
        "Summarize {@quarterly_report.pdf}"

Place the files your script needs inside the Git repository (or a subdirectory of it). Every team member gets the same structure after cloning.

my-project/              ← Git repository root
├── config.yaml          ← cloud configuration
├── daily_report.lm      ← script
├── data/                ← files referenced in with files("./data/")
│   ├── templates/
│   │   └── report_template.html
│   └── reference_data.csv
└── requirements.txt

Rules for team-shared projects

  1. All with files(...) paths must be relative — no ~/, no /absolute/paths
  2. Referenced directories must be inside the Git repository — otherwise teammates won't have them
  3. Git is the recommended source control — Lamia assumes Git when detecting project boundaries for teams
  4. Uploading to Git does NOT eliminate cloud sync — Lamia still syncs files to the GCS bucket for fast runtime access. Git is the source of truth; the bucket is the execution cache.

Sensitive files in team repos

Be careful:

  • Don't commit secrets to the repository
  • Lamia will still block uploads of detected secret files but you will still have a problem if you commit them to the repository.
  • If you have not committed files in the repository lamia --remote command will upload your locale executable and instead of the state that is in the remote git repo as the team would expecct you local state would be running on the cloud. That is why CI/CD flow is a recommened appoach for the team projects.

CI/CD integration (GitHub Flow)

For automated deployments, set up a CI workflow that triggers lamia <script>.lm --remote when relevant files change:

# .github/workflows/lamia-deploy.yml
name: Deploy Lamia Script

on:
  push:
    branches: [main]
    paths:
      - 'daily_report.lm'
      - 'data/**'
      - 'config.yaml'

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pip install "lamia-lang[cloud]"
      - run: lamia daily_report.lm --remote
        env:
          GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GCP_SA_KEY }}

This ensures the cloud deployment updates whenever the script or its data files change in the repository — no manual --remote runs needed.

Benefits over manual sync:

  • Only committed and pushed changes get deployed (no accidental local files)
  • Full audit trail of what was deployed and when
  • Team members don't need individual GCP credentials for deployment

Limitations

  • Scripts using browser automation uses headless browser setup in cloud environments which is inferior to the
  • Only GCP is supported currently; additional providers may be added in future versions

Practical cost note

You usually do not need to build custom cloud agents from scratch to start automation in production. lamia-cloud is designed to cover common agentic workflows with much lower setup and maintenance overhead.