---
title: "API restructuring and sandbox improvements"
date: "2026-03-06"
---

## Provider API keys forwarded to sandboxes

Agent CLI tools running inside Daytona sandboxes can now authenticate with LLM providers automatically. Fabro collects the relevant API key environment variables (e.g. `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`) and forwards them into the sandbox environment, so CLI agents like Claude and Codex can make API calls without manual credential setup.

Previously, sandbox-based agents would fail to authenticate because API keys were only available on the Fabro server, not inside the sandbox.

## Checkpoint pushing for Daytona runs

When a workflow runs on a Daytona sandbox, Fabro now pushes the run branch to origin after each checkpoint. Previously, commits on the run branch were lost when the sandbox was deleted, making it impossible to review intermediate work.

This required upgrading the GitHub App token permission from `contents:read` to `contents:write`. Tokens are automatically refreshed before they expire.

## GitHub App tokens for Daytona

Daytona sandboxes now authenticate git clones using GitHub App Installation Access Tokens (IATs) instead of the user's `gh` CLI token. Each token is scoped to `contents: read` on the specific repository being cloned.

Fabro automatically detects whether a repository is public or private. Public repositories are cloned without credentials. Private repositories get a short-lived, minimally-scoped IAT generated from the GitHub App configured during `fabro install`.

When credentials are missing or misconfigured, Fabro provides specific error messages for each failure mode:
- App not installed for the organization
- Installation suspended
- Repository not accessible to the app
- Authentication failure (bad key or app ID)

<Warning>
**API response shapes have changed.** Flat fields are now nested into typed sub-objects (e.g. `model_id` becomes `model.id`), and relative time strings are replaced with ISO 8601 timestamps. Several endpoints were renamed: `retrieveRunSvg` is now `retrieveRunGraph`, `listRunCompare` is now `retrieveRunDiff`, and `RunListItemStatus` is now `BoardColumn`.

To migrate:
1. Regenerate your TypeScript client: `cd lib/packages/fabro-api-client && bun run generate`
2. Update any code that reads flat fields to use the new nested paths
3. Update any code that displays timestamps — the API now returns ISO 8601 strings instead of pre-formatted relative times
</Warning>

## More

<Accordion title="API">
- API responses now nest related fields into typed sub-objects (e.g. `model_id` becomes `model.id`) and return ISO 8601 timestamps instead of pre-formatted relative strings
- `/runs/{id}/retro` now returns a structured `RetroDetail` schema instead of an untyped JSON blob; `/retros` supports new `workflow` and `smoothness` filter parameters
</Accordion>

<Accordion title="Improvements">
- Adds pagination parameters to `listRunQuestions`, `listRunStages`, and `listRunVerifications` endpoints
- Removes redundant API response types (`StartRunResponse`, `CancelRunResponse`, `SteerRunResponse`, `SubmitAnswerResponse`)
- Filters preamble noise by excluding meta nodes, blank context values, and empty sections
- Fixes 27 OpenAPI spec review items across verifications, insights, HITL, run outputs, workflows, and configuration
</Accordion>

<Accordion title="Fixes">
- Fixed dry-run mode issues with stub scripts, runner working directory, and transition weights
- Fixed GitHub App repo visibility check incorrectly treating 401/403 responses as public
- Fixed duplicate `.env` variables when re-running `fabro install`
</Accordion>
