> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ns.rocks/llms.txt
> Use this file to discover all available pages before exploring further.

# Caching

> Control template build cache behavior and inspect cache events.

Template builds can reuse cached file blobs, layers, and final artifacts when the
builder inputs are compatible.

Agent deployment installs are separate from template build cache. Deployed
agents can build a reusable deployment artifact with `nullspace agent deploy --rebuild`; otherwise they fall back to running the configured `install` command
inside each job run or service start when no custom template already contains
those dependencies. Put heavy system packages or slow base dependency setup in a
custom template when repeated install time is too expensive.

Use `skip_cache=True` to bypass the whole build cache for one build:

<CodeGroup>
  ```python Python SDK theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  build = Template.build(
      builder,
      name="agent-template",
      tags=["stable"],
      skip_cache=True,
  )
  ```

  ```bash CLI theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  nullspace template build \
    --from-python-image 3.12 \
    --name agent-template \
    --tag stable \
    --skip-cache
  ```

  ```bash HTTP API theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  # skip_cache is a top-level flag. Builds stream over SSE — see the API reference.
  curl -N -X POST "${NULLSPACE_API_URL}/v1/templates/build" \
    -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "agent-template",
      "tags": ["stable"],
      "base_image": "python:3.12",
      "skip_cache": true
    }'
  ```
</CodeGroup>

<Note>
  The TypeScript SDK does not expose whole-build `skipCache` or the per-step
  cache boundary yet; use the Python SDK, CLI, or HTTP API.
</Note>

Use a builder cache boundary when only later steps should avoid cache reuse:

<CodeGroup>
  ```python Python SDK theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  builder = (
      Template()
      .from_python_image("3.12")
      .pip_install(["requests"])
      .skip_cache()
      .run_cmd("date > /workspace/build-time.txt")
  )
  ```

  ```bash CLI theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  nullspace template build \
    --from-python-image 3.12 \
    --pip-install requests \
    --step-skip-cache \
    --run-cmd "date > /workspace/build-time.txt" \
    --name agent-template
  ```

  ```bash HTTP API theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  # A cache boundary is a "skip_cache" step in the steps array. Builds stream
  # over SSE — see the API reference for the full schema.
  curl -N -X POST "${NULLSPACE_API_URL}/v1/templates/build" \
    -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "agent-template",
      "base_image": "python:3.12",
      "steps": [
        {"action": "pip_install", "packages": ["requests"]},
        {"action": "skip_cache"},
        {"action": "run", "command": "date > /workspace/build-time.txt"}
      ]
    }'
  ```
</CodeGroup>

Force a copied file to upload even when a cached blob may exist:

<CodeGroup>
  ```python Python SDK theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  builder = builder.copy("./model.bin", "/workspace/model.bin", force_upload=True)
  ```

  ```typescript TypeScript SDK theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  builder.copy("./model.bin", "/workspace/model.bin", { forceUpload: true });
  ```

  ```bash CLI theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
  nullspace template build \
    --from-python-image 3.12 \
    --copy-src ./model.bin --copy-dst /workspace/model.bin --copy-force-upload \
    --name agent-template
  ```
</CodeGroup>

Cache log entries expose a kind, status, reason, and subject when the backend
reports them.

```python theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
status = build.get_status(offset=0)
for entry in status.entries:
    if entry.kind == "cache":
        print(entry.cache_kind, entry.cache_status, entry.cache_reason)
```

Template warm pools are separate from build cache. A pool can only fill when
the resolved template build and runtime artifact are available on compatible
hosts. If artifact preparation blocks fill, pool status reports reasons such as
`artifact_not_ready` or `artifact_prewarm_failed` instead of treating the
condition as a generic cold-start failure.

## Related

* [Build](./build)
* [Logging](./logging)
* [Template warm pools](./warm-pools)
