Skip to Content
Internal docs are powered by Nextra Docs Theme.
ProjectsAgent workspace for sheet population

Agent Workspace for Sheet Population

Date: 2026-06-26 Status: V1 implemented locally; Linear ticket pending while the connector token is expired. Scope: Use the agent’s bash workspace as an auditable scratch area for larger sheet-population workflows, while keeping actual sheet writes behind the existing sheet tools.


Ticket Seed

Title: Add file-backed workspace plans for reliable sheet population

Build a v1 agent workspace pipeline using the existing just-bash VFS. Tools should write large query and sheet outputs to /workspace, allow bash validation and transforms, and let edit_sheets consume validated JSON plans by input_path. This avoids model-side UUID transcription errors, reduces context bloat, and creates auditable intermediate artifacts for compliance test population.

References:

Acceptance criteria:

  • query_data supports output_path.
  • Sheet read tools support output_path.
  • edit_sheets supports input_path.
  • Compliance population instructions prefer schema, candidate, and plan files plus bash validation for large writes.
  • Existing sheet mutation validation remains the only write boundary.

Incident That Motivated This

A local compliance-test populate request failed with:

Operation 1 (add_rows) failed: Column "ab04648e-ea57-4d48-a509-37c817fb0c3697" was not found on this sheet

The relevant AI SDK trace was in rulebase-web/rulebase-api2/.devtools/generations.json, generation 20260626220835362-95d73606, started at 2026-06-26T22:08:36Z.

The model first read the correct sheet schema. The valid columns were:

  • 1dccc9b2-c34d-42db-894f-d652c790a1ef - Ticket
  • 585ebdf2-e9fb-4eb9-8596-17a0ab0c3697 - Agent
  • ab04648e-ea57-4d48-a509-37c817fb0f56 - Customer
  • e1bf61ad-4c7d-4a58-ad72-c49e3049b5de - Date of interaction

The bad column id was a model transcription error: it combined the Customer prefix with the Agent suffix. The sheet tool rejected the operation atomically, so no partial rows were written. The model then retried with valid IDs and succeeded.

The same trace also showed a sampling issue: the SQL used order by random() limit 5 over all conversations, not conversations scoped to the compliance test period. The prompt had a visible label like June 2026, but not a concrete start/end date for the period.

What We Can Learn

The weak point was not the sheet write validator. It did the right thing. The weak point was requiring the model to keep high-entropy identifiers and generated row payloads in its text context while composing the write.

For larger or riskier sheet edits, the agent should:

  1. Export the current sheet schema to a workspace file.
  2. Export candidate records to a workspace file.
  3. Generate a write plan as JSON.
  4. Validate the write plan against the schema with bash tooling before calling edit_sheets.
  5. Submit the already-validated file via edit_sheets({ input_path }).

That makes the workflow inspectable and reduces the chance of UUID copy errors.

Blog Takeaways

The useful pattern from the referenced vertical-agent posts is not “make the spreadsheet itself a live filesystem.” It is to give the model a domain-specific runtime where bulky context can live outside the prompt, while keeping writes mediated by narrow product tools.

Relevant ideas:

  • Use a hierarchy of context. The prompt should hold the goal and decisions; files should hold bulky artifacts; tools should own product mutations.
  • Prefer domain wrappers over raw APIs for common workflows. edit_sheets should remain the only sheet mutation boundary.
  • Let the agent create intermediate artifacts that humans and traces can inspect later.
  • Avoid overloading tool schemas with every possible domain action. A small set of read/export/validate/write tools is easier to reason about.
  • Keep an escape hatch for ad hoc analysis through bash, jq, python3, js-exec, SQL output files, and small validation scripts.

Chosen V1

Use the existing just-bash workspace as an in-memory /workspace filesystem for intermediate artifacts:

/workspace/sheets/<sheet-id>/schema.json /workspace/sheets/<sheet-id>/current.json /workspace/queries/<purpose>.json /workspace/plans/<purpose>.json

The database remains the source of truth. The workspace is scratch space, not a synced copy of sheets. Writing an Excel-like file on the workspace filesystem should not mutate the product sheet. Mutations still go through edit_sheets.

V1 behavior:

  • query_data({ output_path }) writes result rows to a JSON file and returns only preview metadata inline.
  • sheet_get_schema({ output_path }) writes the schema to a JSON file.
  • get_sheet({ output_path }) writes the full sheet read result to a JSON file and keeps the inline response small.
  • edit_sheets({ input_path }) reads an operations JSON plan from /workspace, validates it with the same Zod schema as inline operations, and then runs the normal sheet transaction path.
  • Compliance testing instructions tell the model to sample randomly across the testing period by default unless the user explicitly requests otherwise.
  • Compliance population instructions tell the model to validate every column_id against the current schema before writing.

Query Data Output Limits

The current implementation still caps rows before writing to the workspace. The code path is:

query_data(output_path) -> runQueryData({ includeRows: true }) -> STORAGE_ROW_LIMIT

That means the file receives the full capped result, not an unlimited export. The original reason was defensive: avoid accidental SELECT * calls dumping a very large result into just-bash memory and slowing or destabilizing the agent runtime.

This should probably become two separate limits:

  • Inline preview limit: keep at 200.
  • Workspace output limit: raise to something like 25k or 50k.
  • Returned metadata: include stored_row_count, truncated, and storage_row_limit.

The cap currently protects output size more than database work, because it happens after Postgres returns rows. For truly large exports, we should either require explicit SQL limits or add cursor/streaming support.

Runtime Options Considered

OpenAI Code Interpreter-like runtime: good user model, but not ideal as the product runtime boundary. We need product-specific auth, observability, and sheet mutation validation.

just-bash VFS: best first step because it is already available in the api2 agent runtime. It gives us files, shell tools, and a place to put intermediate artifacts without adding new infrastructure.

just-bash JS/Python: enabled after the first V1 probe. python3 is useful for multi-file JSON validation and generated plan checks. js-exec is useful when JavaScript or TypeScript snippets and Node-like fs/path APIs are more convenient than shell quoting. Keep the bash workspace skill current with the exact runtime contract.

Modal, Cloudflare, or Vercel sandboxes: useful later if we need stronger isolation, heavier compute, package installs, or persistent execution environments. Too much infrastructure for V1.

Follow-Ups

  • Recreate this as a Linear ticket once the Linear connector is re-authenticated.
  • Split query_data inline and workspace limits.
  • Add explicit output metadata for workspace-backed query results.
  • Consider storing generated plan files or their hashes in AI observability traces.
  • Keep the bash workspace skill and tool description synced with the actual enabled just-bash runtime.
Last updated on