| Claude product idea | Gravix Layer approach |
|---|---|
| Many concurrent sessions (agent view) | Many runtime_ids; runtime shell into any one |
| Background a task | Long run_cmd timeout, or pause/resume later |
| Routines (schedule / webhook) | Cron, GitHub Actions, or your API creates a runtime and runs claude -p |
| Dynamic multi-agent workflows | Larger single runtime or fan-out across runtimes |
Prerequisites
export GRAVIXLAYER_API_KEY="your-gravixlayer-api-key"
export ANTHROPIC_API_KEY="sk-ant-..."
export GRAVIXLAYER_CLAUDE_TEMPLATE="agent-claude"
export ANTHROPIC_PROVIDER_ID="..." # from get-started
export CLAUDE_NETWORK_POLICY_ID="..." # must allow api.anthropic.com
Parallel agents (fan-out)
import os
from concurrent.futures import ThreadPoolExecutor, as_completed
from gravixlayer import GravixLayer
client = GravixLayer()
TEMPLATE = os.environ["GRAVIXLAYER_CLAUDE_TEMPLATE"]
PROVIDERS = [os.environ["ANTHROPIC_PROVIDER_ID"]]
POLICIES = [os.environ["CLAUDE_NETWORK_POLICY_ID"]]
ANTHROPIC_API_KEY = os.environ["ANTHROPIC_API_KEY"]
TASKS = [
"Write a minimal FastAPI /health endpoint under /workspace/a and stop.",
"Write a minimal Express /health endpoint under /workspace/b and stop.",
"Write a short Python hello script under /workspace/c/hello.py and stop.",
]
def run_task(prompt: str) -> dict:
rt = client.runtime.create(
template=TEMPLATE,
providers=PROVIDERS,
network_policy_ids=POLICIES,
env_vars={"ANTHROPIC_API_KEY": ANTHROPIC_API_KEY},
timeout=1800,
metadata={"task": prompt[:80]},
)
try:
result = rt.run_cmd(
command="claude",
args=[
"--dangerously-skip-permissions",
"-p",
prompt,
"--output-format",
"text",
],
timeout=1200,
)
return {
"runtime_id": rt.runtime_id,
"exit_code": result.exit_code,
"success": result.success,
"stdout": (result.stdout or "")[:2000],
}
finally:
rt.kill()
with ThreadPoolExecutor(max_workers=3) as pool:
futures = [pool.submit(run_task, t) for t in TASKS]
for fut in as_completed(futures):
print(fut.result())
# Launch three runtimes (example: sequential; parallelize with background jobs if you prefer)
for i in 1 2 3; do
RT=$(gravixlayer runtime create \
--template "$GRAVIXLAYER_CLAUDE_TEMPLATE" \
--provider "$ANTHROPIC_PROVIDER_ID" \
--network-policy "$CLAUDE_NETWORK_POLICY_ID" \
--env "ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY" \
--timeout 1800 \
--wait \
--output json | jq -r '.runtime_id')
echo "started $RT"
gravixlayer runtime exec "$RT" --timeout 1200 -- \
claude --dangerously-skip-permissions \
-p "Write a short note to /workspace/out-$i.txt and stop." \
--output-format text
gravixlayer runtime kill "$RT" -y
done
gravixlayer runtime shell "$RT"
# or continue headless:
gravixlayer runtime exec "$RT" -- \
claude --dangerously-skip-permissions --resume "$SESSION_ID" -p "Continue"
Pause and resume
import json
import os
import time
from gravixlayer.types.runtime import Runtime
rt = Runtime.create(
template=os.environ["GRAVIXLAYER_CLAUDE_TEMPLATE"],
providers=[os.environ["ANTHROPIC_PROVIDER_ID"]],
network_policy_ids=[os.environ["CLAUDE_NETWORK_POLICY_ID"]],
env_vars={"ANTHROPIC_API_KEY": os.environ["ANTHROPIC_API_KEY"]},
timeout=0, # no idle timeout (or set a multi-hour value)
)
print("runtime_id:", rt.runtime_id)
first = rt.run_cmd(
command="claude",
args=[
"--dangerously-skip-permissions",
"--output-format",
"json",
"-p",
"Write /workspace/NOTES.md with a short inventory of /workspace, then stop.",
],
timeout=3600,
)
session_id = json.loads(first.stdout).get("session_id")
print("session_id:", session_id)
rt.pause()
print("paused")
# Later (same or new process):
time.sleep(2)
rt = Runtime.connect(rt.runtime_id)
rt.resume()
print("resumed")
if session_id:
rt.run_cmd(
command="claude",
args=[
"--dangerously-skip-permissions",
"--resume",
session_id,
"-p",
"Append one more bullet to /workspace/NOTES.md.",
],
timeout=900,
)
print(rt.file.read("/workspace/NOTES.md").content)
rt.kill()
gravixlayer runtime pause "$RT"
gravixlayer runtime resume "$RT"
# cURL
API="https://api.gravixlayer.ai/v1"
curl -sS -X POST "$API/agents/runtime/$RT/pause" \
-H "Authorization: Bearer $GRAVIXLAYER_API_KEY"
curl -sS -X POST "$API/agents/runtime/$RT/resume" \
-H "Authorization: Bearer $GRAVIXLAYER_API_KEY"
/workspace).
Scheduled routine (cron)
Complete worker script you can point cron at:#!/usr/bin/env python3
"""morning_triage.py — create Claude sandbox, run a fixed prompt, print output, kill."""
import os
import sys
from gravixlayer import GravixLayer
TEMPLATE = os.environ["GRAVIXLAYER_CLAUDE_TEMPLATE"]
PROVIDER_ID = os.environ["ANTHROPIC_PROVIDER_ID"]
POLICY_ID = os.environ["CLAUDE_NETWORK_POLICY_ID"]
ANTHROPIC_API_KEY = os.environ["ANTHROPIC_API_KEY"]
PROMPT = os.environ.get(
"CLAUDE_PROMPT",
"Summarize what is under /workspace in five bullets. Write the summary to /workspace/briefing.md.",
)
def main() -> int:
client = GravixLayer()
runtime = client.runtime.create(
template=TEMPLATE,
providers=[PROVIDER_ID],
network_policy_ids=[POLICY_ID],
env_vars={"ANTHROPIC_API_KEY": ANTHROPIC_API_KEY},
timeout=1800,
metadata={"job": "morning_triage"},
)
try:
result = runtime.run_cmd(
command="claude",
args=[
"--dangerously-skip-permissions",
"-p",
PROMPT,
"--output-format",
"text",
],
timeout=1200,
)
print(result.stdout)
if not result.success:
print(result.stderr, file=sys.stderr)
return result.exit_code or 1
briefing = runtime.file.read("/workspace/briefing.md")
print("--- briefing.md ---")
print(briefing.content)
return 0
finally:
runtime.kill()
if __name__ == "__main__":
raise SystemExit(main())
# crontab example (weekdays 09:00)
# 0 9 * * 1-5 /usr/bin/env bash -lc 'cd /opt/jobs && source .env && python morning_triage.py'
GitHub Action sketch
# .github/workflows/claude-pr-review.yml
name: Claude PR review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install gravixlayer
- env:
GRAVIXLAYER_API_KEY: ${{ secrets.GRAVIXLAYER_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GRAVIXLAYER_CLAUDE_TEMPLATE: ${{ vars.GRAVIXLAYER_CLAUDE_TEMPLATE }}
ANTHROPIC_PROVIDER_ID: ${{ vars.ANTHROPIC_PROVIDER_ID }}
CLAUDE_NETWORK_POLICY_ID: ${{ vars.CLAUDE_NETWORK_POLICY_ID }}
GIT_CLONE_URL: ${{ github.event.pull_request.head.repo.clone_url }}
GIT_BRANCH: ${{ github.head_ref }}
run: python scripts/claude_pr_review.py
scripts/claude_pr_review.py with runtime.git.clone + claude -p "Review this PR..." using the same patterns as Repo & git.
Operational checklist
- Cap concurrent runtimes (your pool size + service quotas)
- Tag with
metadata(task,pr_number,owner) - Always
killor settimeout - Log
runtime_id, Claudesession_id, andexit_code