Skip to main content

Overview

Weavers are ephemeral Kubernetes pods that run Loom REPL sessions in isolated environments. Each weaver:
  • Runs in the loom-weavers namespace
  • Has configurable resource limits (CPU, memory)
  • Supports custom container images
  • Auto-expires after a configurable lifetime (default: 24 hours, max: 48 hours)
  • Provides terminal access via WebSocket
Permissions: Users can only manage weavers they own. System administrators can manage all weavers. Support users have read-only access.

Create Weaver

POST /api/weaver
Provisions a new weaver pod in Kubernetes.

Request Body

image
string
required
Container image to run (e.g., "ghcr.io/loom/weaver:latest")
org_id
string
required
Organization ID (UUID). User must be a member of this organization.
repo_id
string
Repository ID for repo-scoped secrets access
env
object
default:"{}"
Environment variables as key-value pairs
resources
object
Resource limits:
  • memory_limit: e.g., "8Gi"
  • cpu_limit: e.g., "4"
tags
object
default:"{}"
User-defined metadata tags for filtering
lifetime_hours
integer
Time-to-live in hours (max: 48, default: 24)
command
array
Override container ENTRYPOINT
args
array
Override container CMD
workdir
string
Override container WORKDIR

Response

id
string
Weaver ID
pod_name
string
Kubernetes pod name
status
string
One of: pending, running, succeeded, failed, terminating
created_at
string
ISO 8601 timestamp
image
string
Container image
tags
object
User-defined tags
lifetime_hours
integer
Configured lifetime in hours
age_hours
number
Current age in hours
owner_user_id
string
Owner’s user ID

Example

curl -X POST https://loom.ghuntley.com/api/weaver \
  -H "Authorization: Bearer loom_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "image": "ghcr.io/loom/weaver:latest",
    "org_id": "550e8400-e29b-41d4-a716-446655440000",
    "env": {
      "RUST_LOG": "debug"
    },
    "resources": {
      "memory_limit": "4Gi",
      "cpu_limit": "2"
    },
    "tags": {
      "project": "ai-worker",
      "env": "dev"
    },
    "lifetime_hours": 12
  }'
Response (201 Created):
{
  "id": "weaver_abc123",
  "pod_name": "loom-weaver-abc123",
  "status": "pending",
  "created_at": "2026-03-03T12:00:00Z",
  "image": "ghcr.io/loom/weaver:latest",
  "tags": {
    "project": "ai-worker",
    "env": "dev"
  },
  "lifetime_hours": 12,
  "age_hours": 0.0,
  "owner_user_id": "user_xyz789"
}
Error (403 Forbidden) if user is not an org member:
{
  "error": "forbidden",
  "message": "You are not a member of this organization"
}

List Weavers

GET /api/weavers
Lists weavers. Regular users see only their own weavers. Admins and support see all weavers.

Query Parameters

tag
string[]
Filter by tags (format: key:value). Multiple allowed.

Response

weavers
array
Array of weaver objects
count
integer
Number of weavers returned

Example

# List all weavers for current user
curl -H "Authorization: Bearer loom_sk_..." \
  https://loom.ghuntley.com/api/weavers

# Filter by tags
curl -H "Authorization: Bearer loom_sk_..." \
  "https://loom.ghuntley.com/api/weavers?tag=project:ai-worker&tag=env:prod"
{
  "weavers": [
    {
      "id": "weaver_abc123",
      "pod_name": "loom-weaver-abc123",
      "status": "running",
      "created_at": "2026-03-03T12:00:00Z",
      "image": "ghcr.io/loom/weaver:latest",
      "tags": {
        "project": "ai-worker",
        "env": "dev"
      },
      "lifetime_hours": 12,
      "age_hours": 2.5,
      "owner_user_id": "user_xyz789"
    }
  ],
  "count": 1
}

Get Weaver

GET /api/weaver/{id}
Retrieves details for a specific weaver.

Path Parameters

id
string
required
Weaver ID

Response

Returns a single weaver object.

Example

curl -H "Authorization: Bearer loom_sk_..." \
  https://loom.ghuntley.com/api/weaver/weaver_abc123
Error (403 Forbidden) if user doesn’t have access:
{
  "error": "forbidden",
  "message": "Access denied to this weaver"
}

Delete Weaver

DELETE /api/weaver/{id}
Deletes a weaver pod. Only the owner or system admin can delete.

Path Parameters

id
string
required
Weaver ID

Response

Returns 204 No Content on success.

Example

curl -X DELETE -H "Authorization: Bearer loom_sk_..." \
  https://loom.ghuntley.com/api/weaver/weaver_abc123
Response: 204 No Content

Stream Weaver Logs

GET /api/weaver/{id}/logs
Streams logs from the weaver pod via Server-Sent Events (SSE).

Path Parameters

id
string
required
Weaver ID

Query Parameters

tail
integer
default:"256"
Number of lines to tail from the end
timestamps
boolean
default:"true"
Include timestamps in log lines

Response

Returns text/event-stream with log lines as SSE events.

Example

curl -N -H "Authorization: Bearer loom_sk_..." \
  "https://loom.ghuntley.com/api/weaver/weaver_abc123/logs?tail=100&timestamps=true"
Stream output:
data: 2026-03-03T12:00:00Z Starting Loom REPL...

data: 2026-03-03T12:00:01Z Connecting to LLM provider...

data: 2026-03-03T12:00:02Z Ready for input

Attach to Weaver Terminal

WS /api/weaver/{id}/attach
Attaches to the weaver’s terminal via WebSocket for interactive I/O.

Path Parameters

id
string
required
Weaver ID

Authentication

Use a WebSocket token from /auth/ws-token in the first message:
{"type": "auth", "token": "ws_..."}

Access Levels

  • Full access (owner or admin): Can send input and receive output
  • Read-only (support role): Can only view output

Example

const ws = new WebSocket('wss://loom.ghuntley.com/api/weaver/weaver_abc123/attach');

ws.onopen = () => {
  // Authenticate
  ws.send(JSON.stringify({type: 'auth', token: 'ws_...'}));
  
  // Send input (text or binary)
  ws.send('ls -la\n');
};

ws.onmessage = (event) => {
  // Receive output (binary ArrayBuffer)
  console.log(new TextDecoder().decode(event.data));
};
Read-only notice (for support users):
*** Read-only access: You can view output but cannot send input ***

Cleanup Expired Weavers

POST /api/weavers/cleanup
Triggers cleanup of weavers that have exceeded their lifetime. Requires system admin role.

Query Parameters

dry_run
boolean
default:"false"
If true, only list weavers that would be deleted without actually deleting them

Response

dry_run
boolean
Whether this was a dry run
deleted
string[]
Weaver IDs that were deleted (null in dry run)
would_delete
string[]
Weaver IDs that would be deleted (dry run only)
count
integer
Number of weavers affected

Example

# Dry run
curl -X POST -H "Authorization: Bearer loom_sk_..." \
  "https://loom.ghuntley.com/api/weavers/cleanup?dry_run=true"
{
  "dry_run": true,
  "deleted": null,
  "would_delete": ["weaver_old123", "weaver_old456"],
  "count": 2
}
# Actual cleanup
curl -X POST -H "Authorization: Bearer loom_sk_..." \
  https://loom.ghuntley.com/api/weavers/cleanup
{
  "dry_run": false,
  "deleted": ["weaver_old123", "weaver_old456"],
  "would_delete": null,
  "count": 2
}
Error (403 Forbidden) if not system admin:
{
  "error": "forbidden",
  "message": "System admin access required for cleanup operations"
}

Build docs developers (and LLMs) love