[GH-ISSUE #9] Support direct OCI image in sandbox creation API #4

Closed
opened 2026-10-29 14:18:16 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @yingdi-shan on GitHub (Jul 27, 2026).
Original GitHub issue: https://github.com/kvcache-ai/AgentENV/issues/9

Current Limitation

The sandbox creation API currently requires users to pre-create a template before creating sandboxes. This adds friction to the common workflow of "I have an OCI image, I want to run a sandbox from it."

Meanwhile, the cold creation path already supports OCI images directly, demonstrating that the underlying infrastructure can handle this use case.

Proposed Enhancement

Add a new endpoint to accept an OCI image reference directly:

POST /v3/sandboxes/from-image

When an OCI image is provided, the API should:

  1. Automatically create a template from the provided OCI image
  2. Resume a sandbox from that template
  3. Return the sandbox to the user

This would preserve the internal architecture (templates remain the source of truth for sandbox state) while simplifying the external API surface.

Benefits

User Experience

  • Single API call instead of two-step template-then-sandbox flow
  • Matches user mental model: "run this image"
  • Consistent with Docker/container runtime UX expectations

API Ergonomics

  • Reduces boilerplate in client code
  • Fewer round trips for common use cases
  • Template management becomes an optimization detail rather than a required concept

Backwards Compatibility

  • Existing template-based creation continues to work
  • Users who want explicit template control can still pre-create and reuse templates
  • New direct-image creation is additive

Template Naming Strategy

Auto-generated templates should use template_name (not template_id, which remains a UUID) following the pattern:

{IMAGE_DIGEST}-{CPU}c-{MEM}mb-{DISK}gb

Example: a1b2c3d4e5f6-2c-2048mb-10gb

Preventing Name Collisions

To prevent users from creating templates with names that collide with auto-generated ones (even before the auto-generated template exists), the template creation API must validate and reject user-provided names matching the auto-generation pattern.

Image Digest Extraction

When the user provides an OCI image reference (e.g., ghcr.io/org/image:tag):

  1. Fetch the manifest via regctl manifest get --digest <image>
  2. Extract the manifest digest (e.g., sha256:abc123...def456)
  3. Use the hex portion as IMAGE_DIGEST

Why Manifest Digest?

  • Content-addressed: Same image content → same digest → same template ID
  • Enables reuse: Pulling image:latest multiple times with unchanged content reuses the cached template
  • Immutable: Unlike tags, digests never change for given content
  • Standard: What registries use for immutable references

Template Reuse Logic

Two users requesting the same image with different resource specs will generate different template names due to the CPU/MEM/DISK suffix. If the same user requests the same image+specs twice:

  • First call: Creates template with name a1b2c3d4e5f6-2c-2048mb-10gb, then sandbox
  • Second call: Finds existing template by name, skips creation, resumes sandbox directly

Since user-created templates cannot use the auto-generation naming pattern (rejected at creation time), name collisions between user templates and auto-generated templates are impossible.

Implementation Considerations

Request Schema

{
  "image": "ghcr.io/org/image:tag",
  "vcpu_count": 2,
  "mem_size_mib": 2048,
  "rootfs_size_mib": 10240,
  "env_vars": {
    "KEY": "value"
  },
  "metadata": {
    "user_id": "..."
  }
}

Response Schema

Include both sandbox and template information:

{
  "sandbox_id": "sb_xxx",
  "template_id": "550e8400-e29b-41d4-a716-446655440000",
  "template_name": "a1b2c3d4e5f6-2c-2048mb-10gb",
  "template_created": true,  // or false if reused
  "ip": "...",
  "status": "running"
}

Template Lifecycle

Persistence: Auto-created templates should be persisted with a special marker (e.g., auto_generated: true in metadata) to enable:

  • Cleanup policies (e.g., delete if unused for 7 days)
  • Admin visibility (list auto vs explicit templates)
  • Reuse optimization

Tagging: Add internal metadata to distinguish auto-created templates:

{
  "template_id": "550e8400-e29b-41d4-a716-446655440000",
  "template_name": "a1b2c3d4e5f6-2c-2048mb-10gb",
  "metadata": {
    "auto_generated": true,
    "source_image": "ghcr.io/org/image:tag",
    "source_digest": "sha256:a1b2c3d4e5f6...",
    "created_at": "2026-06-30T12:00:00Z"
  }
}

Error Handling

  • Image pull failures: Return clear errors (not template-not-found)

    • 400 Bad Request: Invalid image reference format
    • 404 Not Found: Image not found in registry
    • 401 Unauthorized: Registry authentication required
    • 500 Internal Server Error: Image resolution failed
  • Template creation failures: Roll back and return error (no orphaned templates)

  • Large images: Consider async creation with status polling for images >1GB

    • Option 1: Synchronous with reasonable timeout (30s)
    • Option 2: Return 202 Accepted with polling endpoint

Rate Limiting

  • Limit auto-template creation per user/node to prevent abuse via repeated large image pulls
  • Reuse logic naturally mitigates this for legitimate repeated requests

Observability

Metrics:

  • agentenv_auto_template_create_total{status="success|failure"}
  • agentenv_auto_template_reuse_total
  • agentenv_sandbox_from_image_duration_seconds

Logs:

  • Log auto-template creation with auto_generated=true field
  • Log template reuse hits
  • Include image digest in structured logs for debugging

Admin API:

  • Filter templates by auto_generated flag
  • Expose auto-template cache hit rate
  • Current template API: POST /v3/templates
  • Current sandbox API: POST /v3/sandboxes
  • Cold creation path (reference implementation for OCI image handling)
Originally created by @yingdi-shan on GitHub (Jul 27, 2026). Original GitHub issue: https://github.com/kvcache-ai/AgentENV/issues/9 ## Current Limitation The sandbox creation API currently requires users to pre-create a template before creating sandboxes. This adds friction to the common workflow of "I have an OCI image, I want to run a sandbox from it." Meanwhile, the cold creation path already supports OCI images directly, demonstrating that the underlying infrastructure can handle this use case. ## Proposed Enhancement Add a new endpoint to accept an OCI image reference directly: ``` POST /v3/sandboxes/from-image ``` When an OCI image is provided, the API should: 1. Automatically create a template from the provided OCI image 2. Resume a sandbox from that template 3. Return the sandbox to the user This would preserve the internal architecture (templates remain the source of truth for sandbox state) while simplifying the external API surface. ## Benefits **User Experience** - Single API call instead of two-step template-then-sandbox flow - Matches user mental model: "run this image" - Consistent with Docker/container runtime UX expectations **API Ergonomics** - Reduces boilerplate in client code - Fewer round trips for common use cases - Template management becomes an optimization detail rather than a required concept **Backwards Compatibility** - Existing template-based creation continues to work - Users who want explicit template control can still pre-create and reuse templates - New direct-image creation is additive ## Template Naming Strategy Auto-generated templates should use **template_name** (not template_id, which remains a UUID) following the pattern: ``` {IMAGE_DIGEST}-{CPU}c-{MEM}mb-{DISK}gb ``` Example: `a1b2c3d4e5f6-2c-2048mb-10gb` ### Preventing Name Collisions To prevent users from creating templates with names that collide with auto-generated ones (even before the auto-generated template exists), the template creation API must **validate and reject** user-provided names matching the auto-generation pattern. ### Image Digest Extraction When the user provides an OCI image reference (e.g., `ghcr.io/org/image:tag`): 1. Fetch the manifest via `regctl manifest get --digest <image>` 2. Extract the manifest digest (e.g., `sha256:abc123...def456`) 3. Use the hex portion as `IMAGE_DIGEST` ### Why Manifest Digest? - **Content-addressed**: Same image content → same digest → same template ID - **Enables reuse**: Pulling `image:latest` multiple times with unchanged content reuses the cached template - **Immutable**: Unlike tags, digests never change for given content - **Standard**: What registries use for immutable references ### Template Reuse Logic Two users requesting the same image with different resource specs will generate different template names due to the CPU/MEM/DISK suffix. If the same user requests the same image+specs twice: - **First call**: Creates template with name `a1b2c3d4e5f6-2c-2048mb-10gb`, then sandbox - **Second call**: Finds existing template by name, skips creation, resumes sandbox directly Since user-created templates cannot use the auto-generation naming pattern (rejected at creation time), name collisions between user templates and auto-generated templates are impossible. ## Implementation Considerations ### Request Schema ```json { "image": "ghcr.io/org/image:tag", "vcpu_count": 2, "mem_size_mib": 2048, "rootfs_size_mib": 10240, "env_vars": { "KEY": "value" }, "metadata": { "user_id": "..." } } ``` ### Response Schema Include both sandbox and template information: ```json { "sandbox_id": "sb_xxx", "template_id": "550e8400-e29b-41d4-a716-446655440000", "template_name": "a1b2c3d4e5f6-2c-2048mb-10gb", "template_created": true, // or false if reused "ip": "...", "status": "running" } ``` ### Template Lifecycle **Persistence**: Auto-created templates should be persisted with a special marker (e.g., `auto_generated: true` in metadata) to enable: - Cleanup policies (e.g., delete if unused for 7 days) - Admin visibility (list auto vs explicit templates) - Reuse optimization **Tagging**: Add internal metadata to distinguish auto-created templates: ```json { "template_id": "550e8400-e29b-41d4-a716-446655440000", "template_name": "a1b2c3d4e5f6-2c-2048mb-10gb", "metadata": { "auto_generated": true, "source_image": "ghcr.io/org/image:tag", "source_digest": "sha256:a1b2c3d4e5f6...", "created_at": "2026-06-30T12:00:00Z" } } ``` ### Error Handling - **Image pull failures**: Return clear errors (not template-not-found) - `400 Bad Request`: Invalid image reference format - `404 Not Found`: Image not found in registry - `401 Unauthorized`: Registry authentication required - `500 Internal Server Error`: Image resolution failed - **Template creation failures**: Roll back and return error (no orphaned templates) - **Large images**: Consider async creation with status polling for images >1GB - Option 1: Synchronous with reasonable timeout (30s) - Option 2: Return `202 Accepted` with polling endpoint ### Rate Limiting - Limit auto-template creation per user/node to prevent abuse via repeated large image pulls - Reuse logic naturally mitigates this for legitimate repeated requests ### Observability **Metrics**: - `agentenv_auto_template_create_total{status="success|failure"}` - `agentenv_auto_template_reuse_total` - `agentenv_sandbox_from_image_duration_seconds` **Logs**: - Log auto-template creation with `auto_generated=true` field - Log template reuse hits - Include image digest in structured logs for debugging **Admin API**: - Filter templates by `auto_generated` flag - Expose auto-template cache hit rate ## Related - Current template API: `POST /v3/templates` - Current sandbox API: `POST /v3/sandboxes` - Cold creation path (reference implementation for OCI image handling)
bsakaguchi 2026-10-29 14:18:16 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kvcache-ai/AgentENV#4
No description provided.