Skip to content

Workspace Pool

Workspace pooling keeps materialized workspaces on disk between eval runs. Instead of cloning repos and checking out files every time, pooled workspaces reset in-place — typically reducing setup from minutes to seconds for large repositories.

Pooling is enabled by default for shared workspaces that define repos. No extra flags needed.

AgentV computes a SHA-256 fingerprint of your repo materialization inputs (repo identity, checkout ref, sparse paths, and ancestor offset) and stores the materialized workspace in a persistent slot:

~/.agentv/workspace-pool/
{fingerprint}/
metadata.json # fingerprint inputs, creation timestamp
slot-0/ # complete workspace (template files + repos)
slot-0.lock # PID-based lock file
slot-1/ # created on concurrent demand
slot-1.lock

On subsequent runs:

  1. AgentV computes the fingerprint from your repo configs
  2. If a matching pool entry exists, it acquires a slot and resets it (git reset --hard + git clean -fd)
  3. Template files are re-copied (repo directories are preserved)
  4. Lifecycle hooks (before_all, etc.) run as normal

Keep templates small. Template files are re-copied into every slot on every run. Use them for lightweight setup — agent skills, configuration files, prompt templates — not large assets. Heavy dependencies belong in repos (pooled and reused) or should be installed by before_all hooks (cached across reuse cycles with fast reset).

The first run materializes from scratch. Every subsequent run reuses the pool — skipping clone and checkout entirely.

Pooling is on by default. To disable it:

Terminal window
agentv eval evals/my-eval.yaml --workspace-mode temp
.agentv/config.local.yaml
execution:
workspace_mode: temp

workspace_mode is a machine-local runtime override. Do not commit it in eval YAML.

By default, pool reset uses git clean -fd which preserves .gitignored files like node_modules/, build/, and compiled binaries. This means before_all build steps survive across reuse cycles.

For strict reset that also removes .gitignored files, use the --workspace-clean full CLI flag:

Terminal window
agentv eval evals/my-eval.yaml --workspace-clean full
ModeGit command.gitignored filesUse case
fast (default)git clean -fdPreservedFast reuse with cached build artifacts
strictgit clean -fdxRemovedClean slate between runs

Eval files that produce the same fingerprint share the same pool. The fingerprint is computed from the resolved workspace configuration, not the file path — so two eval files with identical workspace configs automatically reuse the same pool slots.

The most reliable way to ensure shared pools is to use an external workspace config file:

evals/accuracy.eval.yaml
workspace: ../workspace.yaml
tests:
- id: accuracy-1
input: ...
# evals/regression.eval.yaml
workspace: ../workspace.yaml
tests:
- id: regression-1
input: ...
# workspace.yaml (shared, single source of truth)
template: ./workspace-template
repos:
- path: ./my-repo
repo: https://github.com/org/my-repo.git
commit: main
hooks:
after_each:
reset: fast

Both eval files resolve to the same repos configuration, producing the same fingerprint. They share pool slots, and concurrent runs acquire separate slots from the same pool.

The fingerprint captures repo materialization inputs only — the fields that affect cloned checkout state. Template path is excluded because template files are re-copied on every pool reuse and don’t affect the cloned repos.

Acquisition choices are excluded. A run that acquires https://github.com/org/my-repo.git from a registered project, a configured mirror, the AgentV mirror cache, or the remote URL still maps to the same pool if the declared repo identity and checkout inputs are the same. See Workspace Architecture for the resolver order.

FieldNormalization
Repo pathAs configured (e.g., ./my-repo)
Repo identityNormalized from full clone URL or GitHub org/name shorthand
Checkout refcommit, base_commit, or HEAD
AncestorIncluded when set
Sparse checkout pathsSorted alphabetically

Two configs produce different fingerprints if any of these fields differ. For example, changing the checkout ref from main to v2.0 creates a new pool entry. Changing the template path or template contents does not create a new pool entry.

Pool slots support concurrent eval workers. When running with multiple workers (-w N), each worker acquires its own slot from the pool:

Terminal window
agentv eval evals/my-eval.yaml -w 4

This creates up to 4 slots (slot-0 through slot-3). PID-based lock files prevent two workers from using the same slot simultaneously. If a lock file references a dead process, it’s automatically cleaned up as a stale lock.

The maximum number of pool slots defaults to 10 (capped at 50). Slots are created on demand — a run with 2 workers only creates 2 slots, even if the pool allows 10.

Multiple eval files: When you pass multiple eval files to agentv eval, they run sequentially — one file completes before the next starts (see Parallelism). Within each file, pool slots support concurrent workers as described above.

If you change the workspace config (e.g., update a repo URL or checkout ref), the computed fingerprint changes. AgentV detects this drift by comparing the stored metadata.json fingerprint against the newly computed one:

  • Same fingerprint — existing slots reused as-is
  • Different fingerprint — new pool entry created (old one remains until cleaned)

To reclaim disk space from stale pool entries:

Terminal window
# List all pool entries with size and repo info
agentv workspace list
# Remove all pool entries
agentv workspace clean
# Remove only pools for a specific repo
agentv workspace clean --repo github.com/org/my-repo
# Scan eval files and output a JSON manifest of required git repos
# Useful in CI to determine what to clone before running evals
agentv workspace deps evals/**/*.eval.yaml

Instead of duplicating workspace configuration across eval files, you can reference an external YAML file:

workspace: ./path/to/workspace.yaml

The external file should contain the workspace config object directly, not a nested workspace: key.

The path is resolved relative to the eval file’s directory. Relative paths inside the workspace file (template paths, hook cwd values, and repo paths) resolve from the workspace file’s own directory.

This pattern is especially valuable with pooling: a single workspace.yaml guarantees all eval files that reference it produce the same fingerprint and share the same pool.

For workspaces you manage outside AgentV, bind the existing directory at runtime:

Terminal window
agentv eval evals/my-eval.yaml --workspace-path /path/to/my-workspace

Or persist the machine-local binding outside committed eval YAML:

.agentv/config.local.yaml
execution:
workspace_path: /path/to/my-workspace

AgentV uses a runtime workspace path as-is. It does not auto-materialize repos into that directory; keep repo materialization intent in workspace.repos[] for portable runs, and use workspace_path only when the local directory already exists.

Precedence: CLI flags override project-local .agentv/config.local.yaml, which overrides committed .agentv/config.yaml.

CLI flags --retain-on-success / --retain-on-failure control temporary eval-run workspaces under ~/.agentv/workspaces/... (non-pooled paths).

  • In pooled mode, pool slots are retained for reuse regardless of retention settings.
  • Retention settings do not remove pool entries; use agentv workspace clean for pool cleanup.
  • With --workspace-path or execution.workspace_path, AgentV never deletes the user-provided directory.
ModeSetup costPersistentBuild artifacts preservedConcurrent workers
Pooled (default)First run only; reset on reuseYesYes (.gitignored files)Yes (slot per worker)
Temp (--workspace-mode temp)Full clone + checkout every runNoNoSequential only
Existing path (--workspace-path / execution.workspace_path)Uses the supplied directory as-isYesUser-managedSequential only

Pooling is typically the right default. Consider disabling it when:

  • You need guaranteed clean-slate isolation between runs
  • You’re debugging workspace setup issues and want fresh clones each time
  • You use --workspace-path with a pre-existing local directory (pooling is automatically skipped)
  • You need isolation: per_case (each test gets its own workspace copy; pooling is automatically skipped)