v0.5.5
Upgrade notes
Breaking changes
None for stock templates. If you maintain a custom AGENTS.md that tells the agent to save files into uploads/, see Agent writable area moved to workbench/ below for the recommended (non-mandatory) migration.
Upgrade notes
v0.5.5 picks up OpenClaw 2026.5.20 with the v4 client protocol (was 2026.5.7 / v3), gives every agent a dedicated workbench/ subdirectory in its workspace for files it produces, separate from the user's uploads/, and hardens the Odoo plugin against silent cross-company writes for multi-company databases. It also fixes a confusing failure mode for the built-in image tool on Ollama Cloud stacks, adds an explicit image-model default, patches a reliability edge where chat history could disappear overnight due to OpenClaw's default daily session-reset behavior, and tightens the password-reset path so leaked recovery links cannot leave a logged-in session behind.
Upgrade with the standard flow:
cd /opt/pinchy
sed -i 's/PINCHY_VERSION=v0.5.4/PINCHY_VERSION=v0.5.5/' .env
docker compose pull && docker compose up -d && docker image prune -fNo database migration, no docker-compose.yml change, and no env-var changes are required.
Agent writable area moved to workbench/
Each agent workspace now has three zones (see Agent Workspaces for the full model):
- Workspace root — system files like
SOUL.md,AGENTS.md,IDENTITY.md. Read-only for the agent. uploads/— files the user attached in chat. Created on workspace spawn; previously created lazily by the first upload.workbench/(new) — the agent's own writable area. Created on workspace spawn.pinchy_writeaccepts paths under here without prior user upload.
On v0.5.4 and earlier, a fresh agent could not call pinchy_write until the user had attached at least one file via the chat upload button — pinchy_write to <workspace>/uploads/foo.txt failed with ENOENT because the uploads/ directory didn't exist yet, and writing anywhere else (e.g. the workspace root) was rejected. v0.5.5 provisions both uploads/ and workbench/ on workspace creation, and adds workbench/ to the pinchy_write allow-list as the canonical agent write target.
Existing custom AGENTS.md files keep working. uploads/ remains writable for backward compatibility, so any custom instruction telling the agent to save into uploads/ continues to function. If you maintain such an AGENTS.md, consider updating it to use workbench/ instead — the separation makes "user-uploaded" vs. "agent-produced" easier to reason about. There is no automatic migration; this is a documentation-level switch.
Stock templates do not currently instruct agents to write to either location, so most deployments need no action.
Improved pinchy_write rejection messages
When pinchy_write (or pinchy_read) refuses a path, the error message now includes the configured allow-list so the LLM can retry against the right location:
Access denied: path not in write_paths (allowed: /root/.openclaw/workspaces/<id>/uploads, /root/.openclaw/workspaces/<id>/workbench)
This eliminates a class of stalls where the model would repeatedly try the same wrong path. The error string format is unchanged at the prefix (Access denied: path not in write_paths) so any external monitoring that matched on it continues to work.
Image tool no longer routes to devstral-small-2:24b
On Ollama Cloud stacks without an explicit image model, Pinchy's built-in image tool could pick devstral-small-2:24b and fail with HTTP 400 "Image input is not enabled for this model" mid-chat — confusing because the user never selected devstral. Two fixes ship together:
- Data correction.
devstral-small-2:24bis now flaggedvision: false. Its ollama.com library page lists "Text, Image" as input types, but an empirical smoke test against the live/v1/chat/completionsendpoint (seescripts/verify-ollama-cloud-vision.mjs) confirms the runtime API rejects images with HTTP 400. Devstral is Mistral's coding series, not a vision model. - Explicit image-model default. Pinchy now emits
agents.defaults.imageModel.primaryinto the OpenClaw config, parallel to the existingpdfModelselection. Provider preference order: anthropic > google > openai > ollama-cloud. For ollama-cloud the canonical-vision line wins (qwen3-vl:235b-instruct>qwen3-vl:235b>gemini-3-flash-preview>gemma4:31b), avoiding models likemistral-large-3:675borqwen3.5:397bthat accept image input but mislabel colors.
No action required. The new field is regenerated on startup from your existing provider settings. Operators who want to override the auto-pick can hand-edit agents.defaults.imageModel.primary in openclaw.json.
A companion verification script lives at scripts/verify-ollama-cloud-vision.mjs and can be re-run whenever the Ollama Cloud catalog changes: it tests each curated model against the live API and reports any drift between the vision flag in ollama-cloud-models.ts and runtime acceptance.
CRM & Sales Assistant template gains quotation-ready Odoo models
The CRM & Sales Assistant template now declares three additional Odoo models so a Sales agent can build quotations end-to-end (lead → opportunity → quote with the right VAT regime) and answer "is this invoice paid?":
account.fiscal.position(read + write) — set the customer's tax regime (e.g. "EU B2B reverse-charge") onres.partner.property_account_position_idso future quotations auto-apply the correct taxes.sale.order.line(read + create + write) — inspect and revise quotation line items directly. Normal happy-path writes still go throughsale.order.order_line.account.move(read-only) — look up invoice payment status. Drafting, posting, or amending invoices remains exclusive to the Bookkeeper template, which is governed by a regulated draft-first / four-eyes flow.
A new Fiscal Positions row also appears in the Permissions UI for every Odoo connection (regardless of which template the agent uses), because the schema sync now probes account.fiscal.position as part of the standard accounting category.
Action required for existing CRM agents. Template changes only affect newly-created agents. To grant an existing CRM & Sales Assistant agent access to the new models:
- Open the agent's settings → Permissions.
- Tick
account.fiscal.position(Read + Write),sale.order.line(Read + Create + Write), andaccount.move(Read). - Save.
If you skip this step, the existing agent keeps its previous (narrower) permission set — there is no automatic migration. Newly-created agents from this template pick up the new models automatically.
Chat history persists across daily restarts
OpenClaw ships with a default session.reset: { mode: "daily", atHour: 4 } that rotates the session pointer at 04:00 gateway-local time. Each morning the pointer moved to a new, empty transcript — old history stayed on disk but became unreachable from the Pinchy UI. Pinchy now unconditionally overrides this setting to an idle-based reset with a one-year idle window (mode: "idle", idleMinutes: 525600), which never fires under normal use. Conversations persist until the user explicitly resets with /new or a new chat is started manually.
No action required. The override is written on every Pinchy startup via regenerateOpenClawConfig(). If your instance was affected, existing message files are still on disk under ~/.openclaw/agents/<agentId>/sessions/. Reach out to your administrator if you need to restore a specific session.
OpenClaw 2026.5.20 (protocol v4)
v0.5.5 bumps the bundled OpenClaw runtime from 2026.5.7 to 2026.5.20 and openclaw-node from 0.9.0 to 0.10.0. OpenClaw 2026.5.12 raised MIN_CLIENT_PROTOCOL_VERSION from 3 to 4 — earlier Pinchy releases paired with a self-hosted OpenClaw on a newer tag would fall into an infinite "Waiting for OpenClaw Gateway…" loop with protocol mismatch … expected=4 in the gateway log (#411). The v0.5.5 client advertises protocol v4 and clears the handshake.
OpenClaw 2026.5.12 also stopped self-bootstrapping a random gateway.auth.token on first start and now refuses to bind on a non-loopback interface without one. Pinchy now seeds gateway.auth.{mode,token} before OpenClaw starts so fresh installs (no setup wizard run yet) come up cleanly.
No action required for the standard Docker Compose stack — docker compose pull && up -d swaps both images together. If you run a custom OpenClaw on the side and pair it with openclaw-node directly, bump to 0.10.0 to advertise protocol v4.
Cross-company write protection in Odoo agents
For multi-company Odoo databases, the pinchy-odoo plugin now refuses to write a record whose embedded _pinchy_ref company tag disagrees with the company implied by the relation chain (top-level field only). This stops a class of silent cross-company mistakes — for example, an agent applying a fiscal position from Company A to a partner that lives under Company B, where the write would previously be accepted by Odoo but produce wrong downstream taxes.
Companion changes ship together:
- Auto-include
company_id.odoo_readnow transparently augments the requested field list withcompany_idfor company-scoped models (res.partner,account.fiscal.position, etc.) so the agent always has the company context it needs for the next decision, without bloating the agent's prompt with extra field lists. _pinchy_refcarries the company name. Encoded references now include an optionalcompanyId/companyLabel, and labels are suffixed with the company name ("ACME Bookkeeping [Company A]") when ambiguity exists. The base ordering invariant for_pinchy_refis unchanged.- Better many2one collision errors. When an
odoo_createorodoo_writelookup matches more than one record across companies, the error message now explains the multi-company collision instead of returning a generic "multiple matches" string, so the agent can retry with acompany_idconstraint. - Penny and Bookkeeper templates updated. Both stock templates now instruct the agent to disambiguate multi-company records up front instead of guessing.
Action for existing read-write Odoo agents (Penny / Bookkeeper): newly-created agents get the updated instructions automatically. Existing agents keep their current AGENTS.md unless you re-create them; the runtime guard (cross-company write rejection) applies to all Odoo agents regardless of AGENTS.md content.
Password reset now revokes sessions and writes an audit entry
POST /api/invite/claim on the reset branch is now wrapped in a database transaction with three guarantees (PR #431):
- Existing sessions for the target user are revoked. A leaked or stale session token cannot survive a password reset, so recovery semantics are now sound.
- The four writes (account password, optional user name, invite-token claim, session revocation) are atomic. If any step fails, everything rolls back and the reset link stays usable for a retry.
- An
auth.password_reset_completedaudit entry is written. Password changes are security-sensitive regardless of who triggers them, and CISOs expect to see them in the audit trail.
See the new row in Audit trail → Authentication for the detail-shape.
No action required. Behavior change only on the reset path; ordinary login sessions are untouched.
Universal chat.agent_error audit event
Before v0.5.5, only three error classes wrote audit entries (agent.model_unavailable, agent.upstream_format_error, chat.silent_stream) and each was throttled. The long tail — incomplete-terminal-response failovers, unclassified provider errors, transient blips — had no audit signal at all, which made "how often does this happen?" unanswerable without screenshotting.
A new chat.agent_error event now fires unconditionally for every error chunk plus the synthesised silent-stream timeout. It captures agent, model, an errorClass discriminator (one of failover_incomplete_stream / schema_rejection / model_unavailable / transient / provider_config / silent_stream_timeout / unknown), and an email-scrubbed providerError truncated to 1024 bytes. The specialised events stay in their role as throttled per-class signals; the umbrella runs alongside them, not instead.
A single SQL query grouped by detail->>'errorClass' now aggregates every failure shape for a fleet-wide failure-rate dashboard. See Audit trail → Chat runtime for the full row.
Known issues
uuid< 11.1.1 (GHSA-w5hq-g745-h8pq, moderate). Reachable only viagoogleapis → google-auth-library → gaxios → uuidfrom thepinchy-emailplugin's Gmail integration. The advisory is missing-buffer-bounds checks inv3/v5/v6UUID generation when callers supply their own buffer; Pinchy and its downstream deps only call the no-argumentv4form, so the gadget is unreachable in our code paths. The dep cannot be upgraded without bumpinggoogleapispast a major it has not yet released. Tracked;pnpm audit --audit-level=high --prod(the level our release gate runs at) stays clean.
What's Changed
- fix(image-tool): emit imageModel.primary + demote devstral vision flag by @clemenshelm in #417
- feat(workspaces): add workbench/ subdir for agent writes (closes #418) by @clemenshelm in #419
- fix(odoo): multi-company-aware refs, lookups, and templates by @clemenshelm in #425
- chore(deps): bump openclaw 2026.5.18 + openclaw-node 0.10.0 by @clemenshelm in #421
- chore(deps): bump openclaw 2026.5.12 -> 2026.5.20 by @clemenshelm in #432
- feat(agent-templates): extend CRM & Sales template with quotation-ready models by @clemenshelm in #428
- fix: post-merge review of OC bump PRs (#421 + #432) by @clemenshelm in #434
- fix(openclaw-config): disable default daily session reset by @clemenshelm in #429
- feat(audit): universal chat.agent_error event for every error chunk (#355) by @clemenshelm in #430
- test(ci): activate all dormant checks + block untracked skips by @clemenshelm in #431
- docs: pre-release audit + v0.5.5 coverage by @clemenshelm in #435
Full Changelog: v0.5.4...v0.5.5