All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Approval outcome parsing - custom
ask_approvalbuttons are no longer treated as rejected just because their id is notapprove; known accept/reject ids are classified explicitly, neutral options such as edit requests are reported as selected, and Placet REST fallback responses are normalized to the same review shape as Socket.IO events.
- Targeted Placet HITL reviews - HITL tools now accept an optional
placet_channel_idparameter so agents can send approval, selection, text-input, and form reviews directly to a specific Placet channel. Cron jobs now preserve their PlacetchannelIdand use it as the default HITL review target unless the tool call explicitly overrides it.
- Remote MCP HTTP compatibility - HTTP MCP endpoints without an explicit transport now try Streamable HTTP first and fall back to legacy SSE only when the connection fails before initialization, improving compatibility with stricter SSE servers while preserving explicit
typesettings and per-server headers. - MCP transport config compatibility - existing MCP configs and management clients can continue using legacy
transportfields and values such assse/httporstreamable-http, which are now normalized to Facio's canonical transport settings during config load. - Placet review message ordering - active Placet response streams are now closed before review prompts are sent, keeping approval and HITL messages ordered separately from the draft assistant stream.
- Scoped agent proxy -
tools.proxy/FACIO_PROXYnow applies only to agent-owned web, browser, and exec tools instead of mutating process-wideHTTP_PROXY/HTTPS_PROXY, so Placet, A2A, MCP, media generation, channels, providers, and management clients do not route through the agent proxy by accident.
- Quickstart provider flow - the setup script no longer asks for multiple raw LLM API keys in the terminal. Quickstart now defers provider selection to the existing Placet onboarding flow, where operators choose one provider and Facio uses that provider's recommended default model for the initial setup.
- Placet auto-registration recovery - quickstart installs now write and pass through explicit Placet auto-create-agent settings so first-run agents keep auto-registering even when no agent ID exists yet.
- Startup race during agent creation - the Placet channel now retries automatic agent creation when the Placet API is temporarily unreachable during startup, instead of failing once and then aborting with
agent_id is required.
- Global outbound proxy - added
tools.proxy/FACIO_PROXYas the canonical agent-tool proxy setting for browser, web, and exec subprocesses, with live Management API updates and legacyFACIO_BROWSER_PROXYcompatibility.
- Browser proxy credentials - browser launch proxy configuration now splits username/password out of proxy URLs before handing them to Playwright/Camoufox, fixing authenticated proxies that work for fetch but fail in Firefox/Chromium.
- GitHub backup sync - added optional GitHub backup configuration for the local GitStore, including env and settings API support, Placet SecretStore token resolution, startup pull, auto-push after local commits, and display-safe backup status.
- Private backup repository creation - GitHub backup can now check for the configured repository on startup and create it as a private repo when it is missing, while still remaining fully disabled when no backup config is enabled.
- GitHub token labeling - the shared
GITHUB_TOKENsecret is now labeled as a general GitHub token so it can be used by GitHub backup without conflicting semantically with thegithubskill.
- Exec runtime hardening - Unix
execcommands now run in their own process group so timeouts clean up child processes, and Node/npm/npx invocations get bounded Node heap and quiet npm defaults to reduce container OOM/restart risk during package installs. - Provider override display - Placet settings now show the provider fallback as
defaultinstead of leaking the internal__default__sentinel. - Optional backup robustness - disabled GitHub backup no longer calls GitHub at all, and GitHub API failures during optional remote setup are recorded in backup status instead of breaking agent startup.
- Self-improvement phase pipeline - added phase-aware self-improvement reviews with cadence controls, active phase prompts, staged overlay provenance, conflict reporting, and richer review reports so
/improveproposals can be inspected and rolled back more reliably. - Rich skill manifests - added normalized skill manifests with indexed references, templates, scripts, assets, platform gates, dependency declarations, and startup/create/load dependency policy controls exposed through management settings.
- Skill usage telemetry - added audit events and a
skill_usagetool so self-improvement reviews and operators can inspect skill summary exposure, context loads, explicit reads, missing requirements, and token estimates.
- Self-improvement proposal transport -
/improvenow treats sandboxed file-tool writes, includingpatch_file, as the authoritative proposal source instead of depending on final LLM JSON. - Reflection skill suggestions - Reflection now records reusable workflow suggestions in
memory/SKILL_NOTES.mdfor later Improve review instead of writing skill files directly. - Skill creator scaffolding - the built-in skill creator now emits the richer manifest shape, supports
templates/, and validates script resource contracts with declared help commands.
- Skill dependency safety - metadata and summary reads no longer trigger dependency installation, skill upload dependency installation no longer blocks the aiohttp event loop, unsupported platforms are skipped before install, and management settings accept the same camelCase dependency-policy fields they return.
- Skill availability gates - rich manifest platform, environment, binary, and file requirements now participate in skill availability filtering and summary reporting.
- Improve inconclusive reviews -
/improvenow marks final text-mode tool-call output as failed validation instead of reportingno_changewhen the review never produced a real conclusion. - Agent finalization retry - final answers that contain only text-mode tool-call markup now get one no-tools textual-finalization retry before being accepted as completed output.
- Browser crash recovery - browser tools now surface crashed or closed Playwright pages as explicit resettable errors instead of returning successful empty snapshots.
- Browser screenshot artifacts - repeated screenshots now use unique file names so successful captures do not overwrite each other or look identical to loop detection.
- Runtime self-debugging - log inspection now points agents toward
read_logs(grep=...), runner stuck-loop messages no longer claim successful repeated tool calls are failures, and caught tool exceptions are warning-visible. - Provider capacity handling - DeepSeek-routed models now get a lower default local request concurrency unless operators explicitly override it, and transient retry logs include provider, model, and reasoning context.
- Cron robustness - startup now removes stale protected
dreamsystem jobs superseded by Reflection, and cron jobs that produce only empty or punctuation-only output are treated as failed. - DeepSeek gateway history - gateway-routed DeepSeek thinking models now retain tool history by backfilling empty reasoning metadata instead of repeatedly pruning large conversation chunks.
- Runtime dependency declaration - PyYAML is now declared as a direct runtime dependency for rich YAML skill manifests.
- Central agent versioning - added a Git-backed agent version store for agent-owned workspace state such as memory, skills, scripts, MCP configuration, policy rules, cron jobs, channels, A2A data, and workspace control files. Management clients can now list versions, create checkpoints, inspect diffs, and roll back through
/api/v1/agent/versions, while rollbacks rehydrate MCP, policy, and cron runtime state where possible. - Self-improvement run ledger - added proposal, review, approval, rejection, apply, and rollback tracking for self-improvement runs, with persistent reports, diff artifacts, validation checks, and management API access through
/api/v1/improvement/runs. /improvecommand - added an operator flow where/improveruns an intelligent read-only review and creates a proposal only when useful, while/improve diff [id],/improve apply [id],/improve cancel [id], and/improve rollback <id>manage the proposal lifecycle from chat or CLI channels./versioncommand - added a registered slash command and Placet menu entry that reports Facio runtime version information directly, without falling back to an LLM-generatedpip showtool call.- Automatic self-improvement triggers - self-improvement reviews can now run after goal completion, repeated tool errors, user corrections, or on a scheduled interval, with cooldown and no-change pruning to avoid noisy repeated runs.
- Self-improvement settings API - management settings now expose self-improvement mode, triggers, schedule interval, model/provider overrides, comprehensive scopes, and validation level.
- Reflection auto-apply setting - management settings now expose a separate
reflection_auto_applycontrol so scheduled Reflection application can be disabled without changing self-improvement apply mode.
- Reflection version history - Reflection now writes changes into the central agent version store when available, and
/reflection-logplus/reflection-restorecan inspect or restore those central versions instead of relying only on the legacy memory Git history. - Versioned management mutations - MCP and policy management writes now create central agent-version checkpoints so runtime configuration changes can be audited and rolled back alongside Reflection and self-improvement changes.
- Self-improvement core - manual and automatic reviews now use the agent runner with a narrow read-only tool registry to inspect agent-owned files and runtime evidence before emitting structured proposals.
- Self-improvement review budget - the default self-improvement review loop now allows 12 tool-call iterations and tells the model the current iteration plus remaining budget on every request.
- Pending proposal policy - automatic and manual self-improvement reviews now refuse to create another proposal while a previous proposal is still awaiting review.
- Goal loop commands - added
/goal,/subgoal, and/checklistso users can set a persistent multi-turn objective, inspect or edit its checklist, pause/resume/clear it, and stop active goals through the regular/stoppath. Goal progress now records dedicated audit events and can be bounded with the newagents.defaults.max_goal_turnssetting, including management API and Placet settings support. - Heartbeat runtime controls - added
/heartbeat status|pause|resume|clearfor inspecting Heartbeat state, pausing or resuming the service, and clearing stale Heartbeat runtime metadata or messages without editing session storage by hand.
- Heartbeat and Cron boundary - Heartbeat is now reserved for fuzzy, state-based checks. Clock-based or recurring entries in
HEARTBEAT.mdare detected before LLM execution, skipped with a warning, and documented in the defaultAGENTS.mdandHEARTBEAT.mdtemplates as Cron-only work.
- Provider setup recovery - registered local setup commands such as
/settingscan run when no working LLM provider exists, while provider-dependent commands remain behind the setup gate. Placet provider repair now opens a provider-only form, keeps non-Placet channels on a text fallback, persists the selected default provider, and restores the Placet channel wiring expected by settings and credential forms.
- Audit correlation basics - audit events and token usage now persist turn, trace, parent-run, and channel-instance identifiers, migrate existing SQLite audit databases in place, categorize internal/Reflection audit events, and expose matching audit and usage filters for management clients.
- Audit event context - MCP tool executions are now recorded as
mcp_callevents while preserving the fulltool_name, and LLM request/response audit rows now include explicit status values for management clients.
- DeepSeek thinking history - OpenAI-compatible gateway routes such as OpenCode Go now apply the same DeepSeek reasoning-history cleanup and
reasoning_contentreplay safeguards as the direct DeepSeek provider. - Audit identity defaults - root audit contexts now generate distinct run, turn, and trace identifiers while resumes and subagents continue to inherit the turn and trace identifiers from their parent execution.
- Runtime provider onboarding - when the gateway starts or receives messages without a working LLM provider, it keeps running, answers with a provider-setup hint, reopens Placet onboarding as needed, and hot-loads the validated provider after setup completes.
- Memory consolidation rebranding - memory consolidation now uses Reflection naming across runtime state, commands, configuration, management API, Placet UI, prompt templates, tests, and docs. The manual command is
/reflect, history commands are/reflection-logand/reflection-restore, and management settings usereflection_interval_h.
- Session replay hygiene - conversation replay now strips copied assistant-side runtime artifacts such as message-time prefixes, local image breadcrumbs, and generated-tool echoes before they become in-context examples. Media breadcrumbs are now synthesized only for user messages, while provider reasoning state such as
thinking_blocksis preserved for replay. - DeepSeek and DashScope reasoning compatibility - DeepSeek V4/reasoner history now receives
reasoning_contentbackfill even when reasoning is implicit, and DashScope keeps itsminimumwire value while Facio treats it semantically likeminimal.
- Cron store durability - cron job persistence now uses atomic replace semantics, preserves corrupt
jobs.jsonfiles for inspection, refuses to start from an initially corrupt store instead of silently overwriting it with an empty list, keeps the last good in-memory store during hot-reload corruption, and persists Facio-specific cron payload fields such asdetailPrompt,scripts,requireApproval,channelMeta,sessionKey, andbrowserSession. - Dream cursor safety - Dream mode now advances
.dream_cursoronly after Phase 2 completes successfully, so incomplete tool runs or exceptions retry the batch instead of silently losing history entries. - Exec workspace guard precision - benign device paths such as
/dev/null,/dev/stderr, and/dev/fd/*no longer trip the workspace guard, while real outside-workspace redirects remain blocked. - Repeated workspace-boundary attempts - repeated attempts against the same blocked outside-workspace target are throttled per run, while Facio's existing PolicyGate remains the source of policy decisions.
- Voice transcription resilience - OpenAI and Groq transcription now retry transient HTTP and network failures without retrying non-transient auth/config failures.
- Channel authorization ordering - Email sender allowlist checks now run before attachment extraction and reply-state updates, and Telegram callback authorization now runs before answering callbacks, editing markup, typing indicators, or dispatching message handling.
- Slack channel parity - Slack Socket Mode now handles ask-user button clicks, accepts user
file_shareevents, downloads private Slack files only after channel-aware authorization, preserves explicit DM thread replies without threading top-level DMs, and keeps Slack policy checks channel-aware before handing messages to the bus. - Discord channel authorization coverage - Discord inbound tests now lock in that denied senders do not trigger attachment downloads, typing indicators, reactions, or message dispatch, and that thread channels inherit their parent-channel allowlist.
- CLI input sanitization - interactive CLI input and history storage now reconstruct valid surrogate pairs and replace lone surrogates so malformed terminal input does not crash or corrupt downstream processing.
- MCP config durability - runtime writes to
mcp.jsonnow use same-directory temp files, fsync, and atomic replacement so failed writes preserve the previous config.
- Standalone credential management tool — agents now use a dedicated
manage_credentialstool for listing and deleting stored credential keys and LLM provider credentials, keeping credential workflows separate from MCP server management.
- Shared runtime credential store — the agent loop, MCP manager, and management API now share the same
CredentialStoreinstance in-process, so secrets captured through chat are visible through the API without requiring a restart. - LLM provider key routing — password fields whose keys match registered LLM provider env vars, such as
OPENROUTER_API_KEY, are now routed into the provider configuration as well as the generic credential store.
- Provider API base management — Placet onboarding and the management credentials API now accept provider
apiBase/baseUrlsettings alongside API keys. Local/direct providers such ascustom,vllm,ollama,lm_studio,ovms, andazure_openaican now be configured through the onboarding and management flows, while the existing runtime provider pool continues to consumeproviders.<name>.apiBasewithout additional routing changes.
- Quickstart Compose PID limits — the install-script compose file now sets matching PID limits in both
pids_limitanddeploy.resources.limits.pids, avoiding Docker Compose failures such ascan't set distinct values on 'pids_limit' and 'deploy.resources.limits.pids'during initial setup.
- Central provider error formatting — user-facing LLM error messages are now produced by a single
LLMProvider._format_error_messagehelper. It walks the common JSON shapes (error.message,message,detail,errors[], plainerrorstrings, JSON-encoded text bodies) and falls back cleanly to plain response text orError calling {label}: {exc}when nothing parses. The Anthropic, Azure OpenAI and OpenAI-compatible providers route their_handle_errorpaths through this helper so users see the upstream message instead of a raw JSON dump regardless of provider, and unknown schemas no longer leak asstr(dict). - Provider defaults refreshed — onboarding and provider fallback defaults now use current flagship or widely deployed model IDs: Claude Opus 4.7, GPT-5.5 for OpenAI and OAuth coding providers, Gemini 3.1 Pro Preview, DeepSeek V4 Pro, Groq-hosted GPT-OSS 120B, Mistral Medium 3.5, GLM-4.7, Qwen 3.6 Plus, Kimi K2.6, and MiniMax M2.7. OpenCode Go stays on its OpenAI-compatible
opencode-go/kimi-k2.6default.
- OpenCode Zen Go provider — Facio can now route requests to the OpenCode Zen Go subscription gateway via its OpenAI-compatible chat endpoint. The provider is wired into the registry, config schema (
providers.opencode_go), and Placet onboarding flow (default modelopencode-go/kimi-k2.6, key validation againsthttps://opencode.ai/zen/go/v1/models). SetOPENCODE_GO_API_KEYor configureproviders.opencode_go.api_keyand use models prefixed withopencode-go/.
- Agent loop refactoring completed — the former monolithic
AgentLoopflow was split into focused modules for streaming, loop hooks, channel context, session checkpoint handling, runtime integration, and tool registry setup, reducing coupling and keeping the core loop narrower and easier to validate. - MessageTool pre-send hook isolated per context — the pre-send hook is now stored in a
ContextVarinstead of an instance attribute, preventing cross-session leakage when multiple parallel streaming turns share the sameMessageTool. - Pending-queue race window closed — the agent run loop registers the per-session pending queue synchronously before spawning the dispatch task, so a follow-up inbound arriving in the same loop tick is reliably routed for mid-turn injection instead of racing to spawn a competing task.
/stopand priority commands honour the effective session key — priority-command dispatch andcmd_stopnow look up active tasks by the loop's effective key, so unified-session setups can cancel in-flight work the same way regular sessions do.
all_busyruntime status — when the per-session pending queue is full and a follow-up has to spawn a queued task, the runtime now emits anall_busystatus so the UI can surface saturation distinctly from the regularbusy/activecycle.- Direct unit tests for the extracted agent modules — added focused edge-case tests for
StreamSession,LoopHook,channel_context,SessionCheckpointManager, andPlacetRuntimeIntegration(53 new tests, total 2472 passing).
- Camoufox hardening & fingerprint controls — the browser runtime now supports virtual-display WebGL in Docker, exposes Camoufox spoofing controls for OS, locale, screen bounds, WebGL vendor/renderer, fonts, low-level overrides, and can import BrowserForge fingerprints from settings or env.
- Screenshot controls —
browser_screenshotnow supportsfull_page,width, andheight, so the agent can request either a full-page capture or a constrained viewport shot.
- Browser screenshots default to full pages — tall pages and below-the-fold content are now captured without extra flags.
- Model switching now requires explicit approval —
switch_model action="switch"is gated behind human approval instead of allowing silent self-swaps. - No-vision screenshot handling was softened — screenshots are still saved when the active model cannot inspect images, but the tool only notes that the PNG should not be fed back into
read_file.
- Browser runtime reliability — Docker builds now ship the required Firefox/Camoufox dependencies and prefetch the browser binary, screenshots are stored under the workspace and returned as workspace-relative paths, and BrowserForge fingerprint imports correctly rebuild nested fingerprint objects.
- Browser interaction stability — SPA snapshots no longer fall back to empty pages, navigation/actions wait through hydration, React-controlled inputs re-validate correctly, silent click failures are surfaced, and interactive refs stay in sync with truncated snapshots.
- Browser tool — 14 agent-facing tools (navigation, content, interaction, sessions) with named sessions and persistent profiles, Camoufox (default) and Playwright Chromium backends, per-agent
domain_allowlist/domain_denylistenforced before and after each action (incl. redirects), atomicensure_and_selectfor race-free cron usage, and Management API + Placet UI surface. The new tool is enabled by default.
get_config_path()now honorsFACIO_CONFIG, which keeps tests and operator overrides isolated from the default user config path.
- Interactive CLI now surfaces provider retry-wait notices even when channel progress hints are suppressed.
- First public open-source release of facio.
- Release-preparation pass across packaging, docs, quickstart, and operator-facing surfaces for public open-source use.
- Runtime polish for provider routing, memory isolation, approval flow, and release readiness.
- Hardening for URL handling, channel delivery, and crash-safe persistence.
- Regression coverage refreshed ahead of the public release.
- Final internal refinement pass for memory cleanup, channel context, and safer runtime behavior.
- Internal UX and reliability update for session history, status output, restart handling, and reminders.
- Internal tuning release for dream-mode review and environment resolution.
- Internal milestone for web-tool configuration, routing cleanup, and stronger tool safety.
- Internal milestone expanding management APIs, provider setup, and runtime continuity.
- Internal channel release adding Microsoft Teams support and retiring the legacy WebSocket transport.
- Packaging fix release for Slack runtime dependencies.
- Internal release engineering milestone for Docker images, setup flow, deployment hardening, and project docs.
- Versions
0.16.4through0.16.0focused on policy controls, runtime logging, session handling, and safer operator workflows. - Versions
0.15.0through0.13.0expanded channels, provider integrations, management surfaces, and runtime orchestration. - Versions
0.12.1through0.10.0tightened tooling, memory behavior, execution flow, and reliability work. - Versions
0.9.0through0.7.0pushed container, transport, and workflow foundations forward. - Versions
0.6.0through0.1.0established the initial internal runtime, onboarding flow, and core agent architecture that later became facio.