Skip to content

Workspace Architecture

AgentV workspaces are the shared substrate an eval runs against: templates, fixtures, repositories, and lifecycle hooks. Targets run inside that substrate. When workspace.repos is present, the eval declares repository identity and checkout pins; AgentV decides how to acquire the bytes.

Workspace pooling is enabled by default for shared repo workspaces, so the first run pays materialization cost and later runs reset existing pool slots in place.

Each evaluation run proceeds through these phases:

eval start
|
v
+---------------------------+
| 1. Pool / workspace setup | Acquire pool slot or create temp workspace
+---------------------------+
|
v
+---------------------------+
| 2. Template copy | workspace.template dir -> workspace/
+---------------------------+
|
v
+---------------------------+
| 3. Repo materialization | For each workspace.repos entry:
| a. resolve acquisition | - registered project, configured mirror,
| b. git clone/fetch | AgentV cache, or remote fallback
| c. git checkout <ref> | - check out commit/base_commit/HEAD
+---------------------------+
|
v
+---------------------------+
| 4. before_all hooks | workspace hook, then target hook
+---------------------------+
|
v
+---------------------------+
| 5. Test loop | For each test case:
| before_each -> run -> | workspace hook, target hook, agent,
| after_each | target hook, workspace hook
+---------------------------+
|
v
+---------------------------+
| 6. after_all / cleanup | target hook, workspace hook, cleanup
+---------------------------+

With workspace pooling (the default), steps 2-3 only happen on the first run. Subsequent runs reset the pool slot in-place, skipping clone and checkout entirely.

A workspace.repos[] entry declares identity, not acquisition policy:

workspace:
repos:
- path: ./repo
repo: https://github.com/org/repo.git
commit: 4f3e2d19b6e4e8f1c2b7d9a0e5a6b7c8d9e0f123
sparse: [packages/core]
ancestor: 0

Supported repo fields:

FieldMeaning
pathDirectory inside the workspace where the repo is materialized
repoRepository identity: full clone URL or GitHub org/name shorthand
commitBranch, tag, or SHA to check out after clone
base_commitAlias for commit, useful for SWE-bench-style datasets
sparseOptional sparse-checkout paths
ancestorWalk N parents back after resolving commit / base_commit

source, type, checkout, checkout.resolve, and clone are not part of the repo schema. Acquisition settings are deliberately outside eval YAML so the same benchmark can run against the same repository identity on every machine while each harness uses the fastest safe local source available.

AgentV normalizes repo identity before acquisition. For example, org/repo, https://github.com/org/repo.git, and git@github.com:org/repo.git resolve to the same identity key.

For each materialized repo, AgentV resolves acquisition in this order:

OrderSourceHow it is used
1Registered projectA project in $AGENTV_HOME/projects.yaml whose origin matches the repo identity. AgentV clones from that local checkout with --reference <path> --dissociate, then resets origin to the declared repo URL.
2Configured mirrorA path listed under git_cache.mirrors in $AGENTV_HOME/config.yaml. AgentV uses the same --reference <path> --dissociate flow.
3Mirror cacheAn AgentV-owned bare cache under $AGENTV_DATA_DIR/git-cache/<hash>. Cache population is locked, cloned into a temporary path, verified, and atomically renamed before use.
4Remote cloneThe normalized clone URL from the eval’s repo field.

--dissociate copies the objects needed by the workspace clone and removes the long-lived alternates dependency on the user-owned checkout or mirror. That keeps preserved workspaces and pool slots from breaking later if a local checkout is moved, deleted, or garbage-collected. Local checkouts and mirrors still provide clone speed, but the resulting workspace has its own required Git objects and full reachable history for pinned commits and ancestor checks.

Use git_cache.mirrors when you want AgentV to prefer a known local checkout or bare mirror for a repository identity:

# $AGENTV_HOME/config.yaml
git_cache:
mirrors:
"https://github.com/WiseTechGlobal/CargoWise.git": ~/src/CargoWise
"sympy/sympy": /mnt/git-mirrors/sympy.git

Mirror keys use the same identity normalization as workspace.repos[].repo, so full URLs and GitHub org/name shorthand can match the same eval repo. If a configured mirror path is missing, AgentV warns and continues down the resolver chain.

The mirror setting is machine-local configuration. Keep it out of eval YAML so the eval remains a portable statement of what repository and checkout are being tested.

The eval workspace is the world: the same repos, fixtures, template files, and workspace hooks are shared by every target in the run. A target is the player: the harness under evaluation, plus provider configuration and target-specific setup hooks.

Targets do not declare repos. Keeping repo provenance in the shared eval workspace is what makes multi-target comparison valid: every target sees the same substrate, and differences in results come from the harness, not from a different checkout.

Use target hooks for per-harness setup:

execution:
targets:
- baseline
- name: with-skills
use_target: baseline
hooks:
before_each:
command: ["sh", "-c", "cp -R skills \"{{workspace_path}}/.claude/skills\""]

Workspace hooks run first on setup, then target hooks. Teardown runs in the opposite order. See Target Hooks for the command schema and full lifecycle order.

On Windows, the drive type materially affects file-write throughput during checkout:

Drive typeExample pathCheckout time (large repo)Notes
Standard NTFS (C:)C:\Users\<user>\.agentv~184sNormal Defender/AV interception
Dev Drive (D:)D:\Users\<user>\.agentv~119s~35% faster, lower AV overhead

Windows Dev Drive uses the Resilient File System (ReFS) with a performance mode that reduces antivirus filter overhead for developer workloads. If you evaluate large repos frequently, relocating ~/.agentv to a Dev Drive volume can meaningfully reduce per-run setup time.

To relocate the agentv home directory, set HOME or USERPROFILE to point to the Dev Drive path before running agentv eval:

Terminal window
$env:USERPROFILE = "D:\Users\$env:USERNAME"
agentv eval evals/my-eval.yaml

Long-path support for relocated home directories

Section titled “Long-path support for relocated home directories”

When HOME or USERPROFILE is redirected to another drive, the Git global config (~/.gitconfig) also moves. If core.longpaths=true is not set in the new profile location, git checkout can fail with:

error: unable to create file <path>: Filename too long

Set it globally in the redirected home:

Terminal window
git config --global core.longpaths true

Or add it to the repo-level config after clone (this runs automatically if your before_all script includes it):

Terminal window
git config core.longpaths true

Troubleshooting: eval appears stuck at startup

Section titled “Troubleshooting: eval appears stuck at startup”

Large repo setup is visible now: git clone/fetch progress streams by default, and long-running git operations emit heartbeat messages. If an acquisition times out, the error points to the durable fix: register a matching local checkout, configure git_cache.mirrors, or fix network access.

The old symptom where AgentV looked silent while doing a full remote clone has been fixed. A first run can still take time, especially when a large working tree is checked out, but the active phase should be visible in the terminal.

Terminal window
agentv eval evals/my-eval.yaml --verbose

Verbose mode logs each setup phase with timestamps. Look for:

[workspace] Creating shared workspace...
[workspace] Materializing repo ./repo...
[repo] materialize start path=./repo repo=https://github.com/org/repo.git acquisition=registered-project ...
Cloning into '.../repo'...
[repo] git clone https://github.com/org/repo.git still running after 30s
[workspace] Repo materialization complete
[workspace] Running before_all script...
[workspace] Setup complete, starting test loop

If the log shows clone or fetch progress, git is still acquiring objects. If it shows checkout progress or a long gap after clone completes, the working-tree write is likely the bottleneck. With pooling enabled, this usually only happens on the first run for a given repo fingerprint.

The durable fix for large repos is to make the resolver hit a local source:

  1. Register an existing checkout as an AgentV project so its origin matches workspace.repos[].repo.
  2. Or add a matching entry under git_cache.mirrors in $AGENTV_HOME/config.yaml.

Both paths use local Git objects for speed and full history, then dissociate the workspace clone from user-owned storage.

SymptomLikely causeFix
Clone progress runs for minutes on first runLarge repo acquired from remoteRegister a matching local project or configure git_cache.mirrors; subsequent pooled runs skip clone.
Heartbeat ends with a clone/fetch timeoutRemote network or missing local cacheUse the timeout guidance in the error: local checkout, configured mirror, or network fix.
Stuck at checkout for 2+ minutesLarge repo file materialization after objects are presentExpected for 100k+ files; use Dev Drive on Windows. Subsequent runs use pool.
Filename too long during checkoutMissing core.longpathsgit config --global core.longpaths true
Slow every run despite poolingPool not matching (config drift)Check with agentv workspace list; ensure workspace config is stable
Before_all timeoutSetup script exceeds default 60sIncrease timeout_ms in workspace config

Workspace pooling is enabled by default for shared workspaces with repos. The first run materializes from scratch. Subsequent runs reset the existing workspace in-place (git reset --hard + git clean -fd) — typically reducing setup from minutes to seconds.

To disable pooling for a run:

Terminal window
agentv eval evals/my-eval.yaml --no-pool

See the Workspace Pool guide for details on pool configuration, clean modes, concurrency, and drift detection.