<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Citro</title>
    <description>The latest articles on DEV Community by Citro (joincitro).</description>
    <link>https://dev.to/joincitro</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F13093%2F82b26e27-f320-4e72-9bbe-d7082d62363e.png</url>
      <title>DEV Community: Citro</title>
      <link>https://dev.to/joincitro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joincitro"/>
    <language>en</language>
    <item>
      <title>Build Log — Week of 2026-06-28</title>
      <dc:creator>Bizbox</dc:creator>
      <pubDate>Fri, 17 Jul 2026 22:05:57 +0000</pubDate>
      <link>https://dev.to/joincitro/build-log-week-of-2026-06-28-3279</link>
      <guid>https://dev.to/joincitro/build-log-week-of-2026-06-28-3279</guid>
      <description>&lt;h1&gt;
  
  
  Build Log — Week of 2026-06-28
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Release:&lt;/strong&gt; &lt;a href="https://github.com/zesthq/bizbox/releases/tag/v2026.630.0" rel="noopener noreferrer"&gt;v2026.630.0&lt;/a&gt; · published June 30, 2026&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/zesthq/bizbox" rel="noopener noreferrer"&gt;zesthq/bizbox&lt;/a&gt; · 1 release, 3 PRs merged (2 in window, 1 from prior week included in release)&lt;/p&gt;




&lt;h2&gt;
  
  
  Shipped this week
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🔗 Routine → Workflow Invocation Contract
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/120" rel="noopener noreferrer"&gt;PR #120&lt;/a&gt;&lt;/strong&gt; · @adPalafox · merged June 30 · +1,576 / -74 (30 files)&lt;/p&gt;

&lt;p&gt;The biggest architectural addition this cycle: a versioned, company-local contract that formalises how a routine in autonomous mode can hand work off to a workflow. Previously, the boundary between routines and workflows was implicit; now it's a first-class schema with durable audit records.&lt;/p&gt;

&lt;p&gt;What's in the box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Three selector modes&lt;/strong&gt; — explicit workflow ID, workflow key, or capability. Routines can target workflows by what they &lt;em&gt;can do&lt;/em&gt;, not just by identity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;workflow_invocations&lt;/code&gt; table&lt;/strong&gt; — every routine→workflow handoff is persisted with selector, payload kind, and a link to the resulting workflow run. Full audit trail, safe to replay.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payload kinds&lt;/strong&gt; — markdown or JSON, matching the existing workflow run model so downstream consumers don't need a new code path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zod validators&lt;/strong&gt; covering the full envelope, each selector variant, and the routine invocation request body.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versioned contract constant&lt;/strong&gt; (&lt;code&gt;ROUTINE_WORKFLOW_INVOCATION_CONTRACT_V1&lt;/code&gt;) — the version travels with every handoff so future breaking changes can be detected in the audit log.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This closes the open question from the V1 spec about how autonomous routines compose with workflows.&lt;/p&gt;




&lt;h3&gt;
  
  
  🗓️ Workflow Schedules
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/118" rel="noopener noreferrer"&gt;PR #118&lt;/a&gt;&lt;/strong&gt; · @ralphbibera · merged June 25 (ships in v2026.630.0) · +1,372 / -4 (22 files)&lt;/p&gt;

&lt;p&gt;Board operators can now define recurring workflows with cron semantics — separately from the routine scheduler. Key points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New &lt;code&gt;workflow_schedules&lt;/code&gt; schema + migration (&lt;code&gt;0080_workflow_schedules.sql&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Server tick loop picks up due schedules and enqueues workflow runs automatically&lt;/li&gt;
&lt;li&gt;Full board UI on the Workflow Detail page: create, edit, pause, archive, delete&lt;/li&gt;
&lt;li&gt;UTC-only; skips missed fires by design (no catch-up on deployment restart)&lt;/li&gt;
&lt;li&gt;Covered by focused tests: validators, routes, service scheduling logic, and UI wiring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ops note:&lt;/strong&gt; &lt;code&gt;0080_workflow_schedules.sql&lt;/code&gt; must be applied before the new routes and UI activate. Any active schedules created after migration will be auto-enqueued by the server tick loop — operators should confirm this is expected before creating active schedules in production.&lt;/p&gt;




&lt;h3&gt;
  
  
  📋 Q3 2026 Public Roadmap Update
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/119" rel="noopener noreferrer"&gt;PR #119&lt;/a&gt;&lt;/strong&gt; · @adPalafox · merged June 26 (ships in v2026.630.0) · 1 file&lt;/p&gt;

&lt;p&gt;The public &lt;code&gt;ROADMAP.md&lt;/code&gt; now carries a new &lt;code&gt;✅ AI Workflows&lt;/code&gt; milestone. The evidence table in the PR links six workflow-related merges from Q2 that collectively justify marking this milestone done. Community members watching the roadmap will see the milestone when they pull or browse on GitHub.&lt;/p&gt;




&lt;h2&gt;
  
  
  Decisions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Versioned invocation contract over ad-hoc parameters.&lt;/strong&gt; The team chose to encode the contract version as a first-class constant (&lt;code&gt;ROUTINE_WORKFLOW_INVOCATION_CONTRACT_V1&lt;/code&gt;) rather than relying on implicit compatibility. The version travels in the DB row and can be read from the audit log, making future migrations detectable without schema inspection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Capability-based selector as first-class option.&lt;/strong&gt; Rather than requiring callers to know a workflow's ID or key, routines can now target "the workflow that advertises this capability." This decouples routine authors from specific workflow identities and makes multi-workflow environments more composable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Workflow schedules are UTC-only with no catch-up.&lt;/strong&gt; Missed fires on deployment restart are silently skipped. The team explicitly chose predictability over at-least-once delivery for scheduled workflow runs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Trade-offs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Versioned contract adds migration overhead.&lt;/strong&gt; Every future breaking change to the routine→workflow protocol requires a new version constant, a DB column or separate table, and a compatibility shim for in-flight invocations. The upside (auditability, backward compatibility) is worth it at current scale, but the path from V1 to V2 needs planning before the invocation surface is widely used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Skipping missed schedule fires simplifies ops but surprises automation authors.&lt;/strong&gt; If a deployment takes down the server for 30 minutes, any schedules that would have fired during that window are dropped. This is documented in the PR risks but is not surfaced in the UI. Teams relying on strict at-least-once semantics will need to pair schedules with a monitoring webhook or an idempotent retry layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Three-selector model increases dispatch complexity.&lt;/strong&gt; Capability-based resolution adds a runtime lookup step and raises the question of what happens when multiple workflows claim the same capability. The V1 spec documents the resolver precedence but the UI does not yet expose which workflow would actually receive an invocation for a given capability. Worth revisiting before this pattern is used heavily in production routines.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Open challenges
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Capability namespace governance.&lt;/strong&gt; Now that routines can target workflows by capability string, there is no validation preventing two workflows in the same company from declaring overlapping capabilities. The resolver picks the first match by some ordering, but that ordering is not yet user-visible or configurable. A light namespace convention or a UI warning before this scales would reduce foot-guns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;0080 migration rollout coordination.&lt;/strong&gt; The workflow schedules migration is a prerequisite for the new UI. Teams running rolling deployments need a strategy for the window between when the migration is applied and when the new server version is live — the old server will ignore the new table, so there is no rollback concern, but operators should confirm the migration order in their deployment runbooks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Invocation audit log surface.&lt;/strong&gt; The &lt;code&gt;workflow_invocations&lt;/code&gt; table exists and is populated, but there is no UI or API route yet to query it. The data is there for debugging and compliance, but tooling to surface it is an open task.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Up next:&lt;/em&gt; API and UI surface for the &lt;code&gt;workflow_invocations&lt;/code&gt; audit log · Capability namespace tooling · Community-requested workflow template library.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>automation</category>
      <category>buildinpublic</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Build Log — Week of 5 July 2026</title>
      <dc:creator>Bizbox</dc:creator>
      <pubDate>Fri, 17 Jul 2026 03:56:35 +0000</pubDate>
      <link>https://dev.to/joincitro/build-log-week-of-5-july-2026-3of2</link>
      <guid>https://dev.to/joincitro/build-log-week-of-5-july-2026-3of2</guid>
      <description>&lt;h1&gt;
  
  
  Build Log — Week of 5 July 2026
&lt;/h1&gt;

&lt;p&gt;Four releases shipped this week and the workflow invocation layer got a thorough workout. A new unified concept landed, a security boundary got tightened, and the Pi adapter's logging story is meaningfully cleaner. Here's what moved.&lt;/p&gt;




&lt;h2&gt;
  
  
  Shipped this week
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Merged PRs:&lt;/strong&gt; &lt;a href="https://github.com/zesthq/bizbox/pull/127" rel="noopener noreferrer"&gt;#127&lt;/a&gt; · &lt;a href="https://github.com/zesthq/bizbox/pull/128" rel="noopener noreferrer"&gt;#128&lt;/a&gt; · &lt;a href="https://github.com/zesthq/bizbox/pull/129" rel="noopener noreferrer"&gt;#129&lt;/a&gt; · &lt;a href="https://github.com/zesthq/bizbox/pull/130" rel="noopener noreferrer"&gt;#130&lt;/a&gt; | &lt;strong&gt;Releases:&lt;/strong&gt; &lt;code&gt;v2026.706.0&lt;/code&gt; · &lt;code&gt;v2026.706.1&lt;/code&gt; · &lt;code&gt;v2026.707.0&lt;/code&gt; · &lt;code&gt;v2026.708.0&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Unified workflow bridge context&lt;/strong&gt; (&lt;a href="https://github.com/zesthq/bizbox/pull/127" rel="noopener noreferrer"&gt;PR #127&lt;/a&gt;, released in &lt;code&gt;v2026.706.0&lt;/code&gt;)&lt;br&gt;
Workflow invocation now has a first-class &lt;code&gt;workflowBridge&lt;/code&gt; structure. Before this change, workflow selectors (&lt;code&gt;workflowId&lt;/code&gt;, &lt;code&gt;workflowKey&lt;/code&gt;, &lt;code&gt;capability&lt;/code&gt;) were parsed ad-hoc from disparate payload fields in several places. PR #127 introduces a normalized &lt;code&gt;workflowBridge&lt;/code&gt; object that is extracted once — in &lt;code&gt;normalizePaperclipWakePayload&lt;/code&gt; and &lt;code&gt;buildPaperclipWakePayload&lt;/code&gt; — and propagated consistently from that point forward. Wake prompts now render a "Workflow target" line when a bridge is present, which makes debugging a failed or ambiguous workflow invocation significantly faster. Error messages from &lt;code&gt;resolveWorkflowByInvocationTarget&lt;/code&gt; also gained formatted selector dumps so you can see exactly what was tried.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow bridge extraction from description fallback&lt;/strong&gt; (&lt;a href="https://github.com/zesthq/bizbox/pull/128" rel="noopener noreferrer"&gt;PR #128&lt;/a&gt;, released in &lt;code&gt;v2026.706.1&lt;/code&gt;)&lt;br&gt;
Building on the bridge unification above: a new &lt;code&gt;readWakeWorkflowBridgeFromDescription&lt;/code&gt; function can extract workflow bridge selectors from the issue &lt;code&gt;description&lt;/code&gt; field when the structured field is absent. The explicit bridge always wins over anything parsed from free text, so the precedence is unambiguous. This closes a gap where wake payloads constructed from older issue shapes would silently drop their workflow context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pi adapter log sanitization&lt;/strong&gt; (&lt;a href="https://github.com/zesthq/bizbox/pull/129" rel="noopener noreferrer"&gt;PR #129&lt;/a&gt;, released in &lt;code&gt;v2026.707.0&lt;/code&gt;)&lt;br&gt;
The &lt;code&gt;pi-local&lt;/code&gt; adapter previously piped Pi's raw JSONL stdout straight through into logs and &lt;code&gt;resultJson.stdout&lt;/code&gt;, which could unintentionally include session internals in log sinks. PR #129 inserts a &lt;code&gt;formatPiProgressMessage&lt;/code&gt; layer: Pi's stdout is buffered line-by-line, each line parsed as a Pi event, sensitive fields redacted, and a human-readable progress summary emitted instead. The &lt;code&gt;execute&lt;/code&gt; function now returns a &lt;code&gt;sanitizedStdout&lt;/code&gt; field used in place of raw output. Logs stay useful — you still see what the agent is doing — without leaking internals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Routine workflow invocation permission hardening&lt;/strong&gt; (&lt;a href="https://github.com/zesthq/bizbox/pull/130" rel="noopener noreferrer"&gt;PR #130&lt;/a&gt;, released in &lt;code&gt;v2026.708.0&lt;/code&gt;)&lt;br&gt;
A new &lt;code&gt;assertCanDispatchWorkflowInvocation&lt;/code&gt; check in the &lt;code&gt;/routines/:id/workflow-invocations&lt;/code&gt; route ensures agents can only dispatch invocations for routines and routine runs they are actually authorized to access. The previous check was coarser. The service layer gained a &lt;code&gt;getRun&lt;/code&gt; method to support the ownership lookup. Tests cover the edge cases: cross-routine dispatch attempts, unknown source runs, and routine assignment mismatches.&lt;/p&gt;




&lt;h2&gt;
  
  
  Decisions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;workflowBridge&lt;/code&gt; as a single normalized contract.&lt;/strong&gt; Rather than having each consumer re-derive the workflow selector from whatever fields happen to be present, the team landed on one normalization pass at wake-payload construction time. Downstream consumers receive a consistent object or nothing — no partial states. This is a deliberate simplification over the previous implicit parsing spread.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description-parsing as a fallback, not a primary path.&lt;/strong&gt; PR #128 explicitly establishes that free-text description parsing is a backward-compat escape hatch. Structured fields always win. This keeps the system honest: relying on description text for routing is a known fragility, and the new code names it as such.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pi log sanitization is opt-out of raw, not opt-in to safe.&lt;/strong&gt; The new approach treats raw JSONL output as unsafe by default and requires the new formatter to produce anything that leaves the adapter. This is the stricter posture, and the right one for an observability surface that integrates with external log sinks.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Trade-offs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Description parsing adds a format dependency.&lt;/strong&gt; The &lt;code&gt;readWakeWorkflowBridgeFromDescription&lt;/code&gt; fallback can break silently if the description format drifts. The tests added in PR #128 cover the current format, but this is a surface worth keeping an eye on if issue description templates change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pi progress message buffering introduces latency.&lt;/strong&gt; Buffering stdout by line and formatting before forwarding means live log consumers see progress messages rather than the raw stream. In practice this is negligible, but very high-throughput Pi executions will see slightly delayed log output compared to pass-through. The safety benefit outweighs this for the vast majority of workloads.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Open challenges
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PR #131&lt;/strong&gt; ("Show workflow run input above operator console") landed late Friday (2026-07-10) — operator UX for inspecting workflow run input is now in the codebase. No remaining open challenge here; see the Up next section for what follows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependabot setup:&lt;/strong&gt; The &lt;code&gt;dependabot.yml&lt;/code&gt; config (PR #123) merged on 2026-07-16, putting automated dependency management on a regular cadence. PR #125 (13 npm dependency updates across 8 directories) remains open and is the next queue item.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;v2026.706.0&lt;/code&gt; release bundled the previous week's Build Log content drop alongside the workflow bridge feature. Future releases may want to separate community content merges from product code merges to keep the changelog cleaner.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Up next
&lt;/h2&gt;

&lt;p&gt;PR #131 shipped — workflow run input is now visible in the operator console. The next interesting area to watch is how the &lt;code&gt;workflowBridge&lt;/code&gt; normalization holds up against more complex multi-capability workflow graphs. Expect the remaining Dependabot PR (#125) to clear once the new config is fully reviewed.&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>devjournal</category>
      <category>showdev</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Build Log — Week of 21 June 2026</title>
      <dc:creator>Bizbox</dc:creator>
      <pubDate>Fri, 03 Jul 2026 08:36:12 +0000</pubDate>
      <link>https://dev.to/joincitro/build-log-week-of-21-june-2026-50ag</link>
      <guid>https://dev.to/joincitro/build-log-week-of-21-june-2026-50ag</guid>
      <description>&lt;h1&gt;
  
  
  Build Log — Week of 21 June 2026
&lt;/h1&gt;

&lt;p&gt;Another solid week in the Bizbox engine room. Two meaningful features landed for the Workflows surface, a new release was tagged, and the dev-community side closed out the July 2026 Deep Dive syndication. Here's what moved.&lt;/p&gt;




&lt;h2&gt;
  
  
  Shipped this week
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Merged PRs:&lt;/strong&gt; &lt;a href="https://github.com/zesthq/bizbox/pull/116" rel="noopener noreferrer"&gt;#116&lt;/a&gt; · &lt;a href="https://github.com/zesthq/bizbox/pull/117" rel="noopener noreferrer"&gt;#117&lt;/a&gt; · &lt;a href="https://github.com/zesthq/bizbox/pull/118" rel="noopener noreferrer"&gt;#118&lt;/a&gt; | &lt;strong&gt;Release:&lt;/strong&gt; &lt;code&gt;v2026.622.0&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Workflow run cancellation&lt;/strong&gt; (&lt;a href="https://github.com/zesthq/bizbox/pull/116" rel="noopener noreferrer"&gt;PR #116&lt;/a&gt;, released in &lt;code&gt;v2026.622.0&lt;/code&gt;)&lt;br&gt;
Board operators can now cancel a workflow run mid-flight — whether it's queued, actively running, or sitting in an awaiting-human handoff. A new &lt;code&gt;POST /api/workflow-runs/:id/cancel&lt;/code&gt; route marks the run and all open phases as &lt;code&gt;cancelled&lt;/code&gt;, records a &lt;code&gt;workflow.run_cancelled&lt;/code&gt; activity event, and cleans up any pending ClickUp-backed handoffs. The workflow detail page gains a clearly destructive "Cancel run" control in the Pipeline header. Before this, the board had to either wait out a stalled run or intervene at the database level. Now it's a first-class operator action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow schedules&lt;/strong&gt; (&lt;a href="https://github.com/zesthq/bizbox/pull/118" rel="noopener noreferrer"&gt;PR #118&lt;/a&gt;)&lt;br&gt;
Recurring workflow runs are now a thing. A new &lt;code&gt;workflow_schedules&lt;/code&gt; table, cron-backed scheduler integration, and board-only CRUD routes let you define a prompt template that fires on a schedule — entirely separate from the existing Routines system. The workflow detail UI adds create/edit/pause/archive/delete controls for schedules. Today this is UTC-only with skip-missed-fires semantics; time-zone support is the natural follow-on. &lt;em&gt;Merged this week; ships in the next release (&lt;code&gt;v2026.630.0&lt;/code&gt;).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;July 2026 Deep Dive syndication log&lt;/strong&gt; (&lt;a href="https://github.com/zesthq/bizbox/pull/117" rel="noopener noreferrer"&gt;PR #117&lt;/a&gt;)&lt;br&gt;
The July 2026 Deep Dive ("Workflows as a First-Class Primitive") landed on Dev.to and X. Discourse hit a 503 read-only window and needs a retry; GitHub publisher is not yet implemented.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Release &lt;code&gt;v2026.622.0&lt;/code&gt;&lt;/strong&gt; — released Monday, 22 June, capturing the cancellation feature and the Deep Dive content drop.&lt;/p&gt;




&lt;h2&gt;
  
  
  Decisions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workflow schedules live alongside Routines, not inside them.&lt;/strong&gt; Routines are agent-assignment–driven; Workflow schedules are company-scoped and dispatch rendered prompt bodies directly. Keeping them separate avoids adding workflow-specific semantics to an already established abstraction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UTC-only for schedule dispatch.&lt;/strong&gt; Deliberate simplification for v1. The skip-on-missed-fires default follows the Routine precedent already set in the codebase.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cancellation cleanup runs synchronously in the route handler.&lt;/strong&gt; ClickUp handoff closure happens immediately on cancel rather than via a background job to keep the operator's cancel action visibly atomic.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Trade-offs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cancellation currently relies on an in-memory child-process registry for active local execution. Forced-shutdown edge cases fall back to the existing interrupted-run recovery path — that path works, but it's indirect.&lt;/li&gt;
&lt;li&gt;The cancel route tests AND the embedded-Postgres workflow-service cancellation tests were written but could not execute in the PR sandbox due to &lt;code&gt;EPERM&lt;/code&gt; on localhost sockets. Coverage there is currently code-review + typecheck rather than a green Vitest run.&lt;/li&gt;
&lt;li&gt;Workflow schedules require migration &lt;code&gt;0080_workflow_schedules.sql&lt;/code&gt; to be applied before the new routes go live. Deployments need to sequence this explicitly.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Open challenges
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Discourse retry for the Deep Dive is outstanding — someone needs to re-run content-syndication once the forum is writable again.&lt;/li&gt;
&lt;li&gt;GitHub publisher for the content-syndication pipeline is not yet implemented; the Deep Dive has no GitHub presence yet.&lt;/li&gt;
&lt;li&gt;Time-zone support for workflow schedules is an obvious community ask; worth opening a tracking issue.&lt;/li&gt;
&lt;li&gt;ADK workflow graph parsing landed in PR #113 last week and is fairly complex. Would benefit from a follow-up integration test pass against real multi-branch workflow definitions.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>automation</category>
      <category>buildinpublic</category>
      <category>devjournal</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Bizbox Q3 2026 Public Roadmap Update</title>
      <dc:creator>Bizbox</dc:creator>
      <pubDate>Fri, 26 Jun 2026 01:54:41 +0000</pubDate>
      <link>https://dev.to/joincitro/bizbox-q3-2026-public-roadmap-update-137a</link>
      <guid>https://dev.to/joincitro/bizbox-q3-2026-public-roadmap-update-137a</guid>
      <description>&lt;h1&gt;
  
  
  Bizbox Q3 2026 Public Roadmap Update
&lt;/h1&gt;

&lt;p&gt;Every quarter we publish an updated snapshot of what shipped, what changed direction, and where we are heading next. This is the Q3 2026 edition.&lt;/p&gt;

&lt;p&gt;The big update this quarter: &lt;strong&gt;AI Workflows has crossed the finish line.&lt;/strong&gt; 🎉&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Just shipped: AI Workflows
&lt;/h2&gt;

&lt;p&gt;Bizbox now supports first-class multi-step workflow orchestration alongside the existing task model. Here is what is in the box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sequential and branching workflow steps&lt;/strong&gt; — compose multi-step automations with conditional branches and join nodes (including Google ADK patterns).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human-checkpoint steps&lt;/strong&gt; — any workflow step can hand off to ClickUp for human approval and automatically continue once approved. The exact same pattern the Bizbox heartbeat uses is now available to any workflow you build.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Import from version-controlled directories&lt;/strong&gt; — define workflow definitions in files, check them in, and import them straight into Bizbox.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt templates&lt;/strong&gt; — pre-fill run inputs to make repeated workflows faster and more consistent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run history detail page&lt;/strong&gt; — selectable run history on the workflow detail page so you can inspect past executions inline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of this shipped across six merged PRs in June 2026 (PRs &lt;a href="https://github.com/zesthq/bizbox/pull/91" rel="noopener noreferrer"&gt;#91&lt;/a&gt;, &lt;a href="https://github.com/zesthq/bizbox/pull/96" rel="noopener noreferrer"&gt;#96&lt;/a&gt;, &lt;a href="https://github.com/zesthq/bizbox/pull/103" rel="noopener noreferrer"&gt;#103&lt;/a&gt;, &lt;a href="https://github.com/zesthq/bizbox/pull/111" rel="noopener noreferrer"&gt;#111&lt;/a&gt;, &lt;a href="https://github.com/zesthq/bizbox/pull/112" rel="noopener noreferrer"&gt;#112&lt;/a&gt;, &lt;a href="https://github.com/zesthq/bizbox/pull/113" rel="noopener noreferrer"&gt;#113&lt;/a&gt;) and landed in &lt;strong&gt;v2026.618.0&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where to contribute
&lt;/h3&gt;

&lt;p&gt;Workflow graph visualization and layout improvements are actively in flight — take a look at the &lt;a href="https://github.com/zesthq/bizbox/pulls" rel="noopener noreferrer"&gt;open PRs&lt;/a&gt; for the current shape. Feedback on the prompt-template API and ClickUp handoff ergonomics is welcome in Discussions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Milestones: current state
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Milestone&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Plugin system&lt;/td&gt;
&lt;td&gt;✅ Shipped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenClaw / claw-style agent employees&lt;/td&gt;
&lt;td&gt;✅ Shipped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companies.sh — import/export&lt;/td&gt;
&lt;td&gt;✅ Shipped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Easy AGENTS.md configurations&lt;/td&gt;
&lt;td&gt;✅ Shipped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skills Manager&lt;/td&gt;
&lt;td&gt;✅ Shipped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scheduled Routines&lt;/td&gt;
&lt;td&gt;✅ Shipped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Better Budgeting&lt;/td&gt;
&lt;td&gt;✅ Shipped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent Reviews and Approvals&lt;/td&gt;
&lt;td&gt;✅ Shipped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiple Human Users&lt;/td&gt;
&lt;td&gt;✅ Shipped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deliverables &amp;amp; Work Products&lt;/td&gt;
&lt;td&gt;✅ Shipped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AI Workflows&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅ Shipped — NEW this quarter&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory / Knowledge&lt;/td&gt;
&lt;td&gt;⚪ Planned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud / Sandbox agents&lt;/td&gt;
&lt;td&gt;⚪ Planned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise SSO / SAML Integration&lt;/td&gt;
&lt;td&gt;⚪ Planned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Role-Based Access Control (RBAC)&lt;/td&gt;
&lt;td&gt;⚪ Planned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kubernetes / Helm Deployment&lt;/td&gt;
&lt;td&gt;⚪ Planned&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The full &lt;a href="https://github.com/zesthq/bizbox/blob/master/ROADMAP.md" rel="noopener noreferrer"&gt;ROADMAP.md&lt;/a&gt; is always the authoritative reference — it includes the detailed write-up for each shipped and planned milestone.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;The planned milestones are still the planned milestones. The team is focused on Memory / Knowledge as the next major theme: durable memory, better recall of prior decisions and context, and a cleaner knowledge layer that doesn't turn Bizbox into a generic chat app.&lt;/p&gt;

&lt;p&gt;Questions, ideas, or contributions? Open a &lt;a href="https://github.com/zesthq/bizbox/discussions" rel="noopener noreferrer"&gt;Discussion&lt;/a&gt; or drop a comment here.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>news</category>
      <category>product</category>
    </item>
    <item>
      <title>Deep Dive: Workflows as a First-Class Primitive — How Bizbox Added a Full Pipeline Platform in June 2026</title>
      <dc:creator>Bizbox</dc:creator>
      <pubDate>Fri, 19 Jun 2026 08:04:39 +0000</pubDate>
      <link>https://dev.to/joincitro/deep-dive-workflows-as-a-first-class-primitive-how-bizbox-added-a-full-pipeline-platform-in-june-2ebk</link>
      <guid>https://dev.to/joincitro/deep-dive-workflows-as-a-first-class-primitive-how-bizbox-added-a-full-pipeline-platform-in-june-2ebk</guid>
      <description>&lt;h1&gt;
  
  
  Deep Dive: Workflows as a First-Class Primitive — How Bizbox Added a Full Pipeline Platform in June 2026
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;July 2026&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Workflows Needed to Be a Primitive
&lt;/h2&gt;

&lt;p&gt;Bizbox has always had two execution models: &lt;strong&gt;issues&lt;/strong&gt; (discrete tasks, picked up by an agent in a heartbeat, one agent at a time) and &lt;strong&gt;routines&lt;/strong&gt; (recurring tasks, scheduled or webhook-triggered, also single-agent). Both models work well for bounded, interruptible work — the kind of thing an agent can start, pause, and resume across heartbeats.&lt;/p&gt;

&lt;p&gt;But a class of workflows doesn't fit that shape. Consider a data pipeline that ingests a report, runs several analysis steps in sequence, calls an external API mid-flight, waits for a human to review an intermediate output, and only then writes results to a deliverable. That's a multi-step, multi-agent-or-single-agent-but-long-running, human-in-the-loop pipeline. Forcing it through the issue model means either one enormous heartbeat (fragile, timeout-prone) or a web of child issues with manual sequencing (brittle, hard to observe).&lt;/p&gt;

&lt;p&gt;The team's answer, landed on June 3 in &lt;a href="https://github.com/zesthq/bizbox/pull/86" rel="noopener noreferrer"&gt;PR #86&lt;/a&gt;, was to introduce &lt;code&gt;Workflows&lt;/code&gt; as a new company-scoped primitive — explicitly separate from issues and routines — backed by Google's Agent Development Kit (ADK) runtime.&lt;/p&gt;

&lt;p&gt;This post walks through what was built, why the design is structured the way it is, and what the month of iteration on top of that foundation revealed.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Foundation: What Shipped on Day One
&lt;/h2&gt;

&lt;p&gt;PR #86 was a substantial landing. The scope, compressed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A new &lt;code&gt;workflows&lt;/code&gt; table&lt;/strong&gt; and corresponding API routes. Workflows are first-class entities in the database, not a special issue type or a routine variant. They have their own namespace, their own run records, and their own lifecycle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google ADK-backed execution.&lt;/strong&gt; Each workflow run spawns a Python ADK process. The Bizbox server acts as the orchestrator: it provisions the ADK environment, passes the workflow's Python source and any input, and streams the resulting console output into a run record.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run records with persisted deliverables.&lt;/strong&gt; A workflow run isn't just a log entry — it produces structured output. Deliverables (files, structured data, artifacts) are attached to the run record and exposed through the same deliverables API used elsewhere in Bizbox.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pipeline graph rendering.&lt;/strong&gt; The ADK runtime produces a graph of the pipeline's phases — each workflow step is a node; execution order and branching are edges. Bizbox instruments this graph and renders it in the UI, so operators can see the full pipeline topology at a glance, not just a flat console log.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;input()&lt;/code&gt; bridge.&lt;/strong&gt; PR #86 also introduced the first version of &lt;code&gt;input()&lt;/code&gt; monkey-patching: when the ADK Python process calls &lt;code&gt;input()&lt;/code&gt;, Bizbox intercepts it instead of blocking the process. This is the foundational seam that makes human-in-the-loop workflows possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workflow detail view and navigation.&lt;/strong&gt; The UI got a workflows navigation item, a workflow list, and a workflow detail page showing pipeline graph, run history, console output, and deliverables.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the full vertical stack — schema, API, runtime, and UI — in a single PR. That's worth noting: rather than landing a stub and iterating, the team shipped the complete primitive. The following three weeks were refinement and extension, not completion.&lt;/p&gt;




&lt;h2&gt;
  
  
  Instrumentation: Making &lt;code&gt;input()&lt;/code&gt; Reliable Across Environments
&lt;/h2&gt;

&lt;p&gt;ADK workflows are Python programs. Python programs that need human input call &lt;code&gt;input()&lt;/code&gt;. In a typical ADK pipeline, &lt;code&gt;input()&lt;/code&gt; blocks the process until the user types something. That model doesn't work in a server-managed runtime — you can't block a server process on stdin.&lt;/p&gt;

&lt;p&gt;PR #86 introduced the solution: monkey-patching the Python environment so that &lt;code&gt;input()&lt;/code&gt; calls are intercepted rather than blocking. The initial implementation worked but had cross-environment reliability issues — the monkey-patch didn't take effect consistently across all Python runtime configurations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/91" rel="noopener noreferrer"&gt;PR #91&lt;/a&gt;, merged two days after launch, fixed this cross-environment gap and completed the integration by wiring the intercepted &lt;code&gt;input()&lt;/code&gt; call through to the awaiting-human bridge. Instead of blocking the process, the intercepted call now routes through the &lt;a href="https://github.com/zesthq/bizbox/blob/main/community/deep-dives/2026-06.md" rel="noopener noreferrer"&gt;provider-agnostic awaiting-human bridge&lt;/a&gt; — the same durable coordination layer that issues use for human handoffs — and suspends the workflow run until the human responds through their configured channel.&lt;/p&gt;

&lt;p&gt;This is an elegant use of the bridge architecture. The workflow author writes standard Python. The &lt;code&gt;input()&lt;/code&gt; call expresses the semantic intent ("I need a human here") without requiring any Bizbox-specific SDK. Bizbox instruments the runtime, and the bridge handles the rest: notification delivery via the configured transport adapter, polling, reply ingestion, and resume. ClickUp is the current default transport, but the bridge is designed to support other providers without changes to the workflow code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/96" rel="noopener noreferrer"&gt;PR #96&lt;/a&gt; continued this work, improving the full lifecycle of the handoff for workflow runs — specifically ensuring that the workflow's run state is correctly reflected while a handoff is pending and that the run resumes cleanly when the human responds.&lt;/p&gt;




&lt;h2&gt;
  
  
  Portability: Import and Export
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/99" rel="noopener noreferrer"&gt;PR #99&lt;/a&gt; and &lt;a href="https://github.com/zesthq/bizbox/pull/103" rel="noopener noreferrer"&gt;PR #103&lt;/a&gt; added workflow import/export.&lt;/p&gt;

&lt;p&gt;These PRs matter architecturally for a reason that isn't immediately obvious: they establish that Workflows are a portable unit of company configuration, not a runtime-only artifact.&lt;/p&gt;

&lt;p&gt;Bizbox's import/export system lets operators snapshot a company's configuration — agents, routines, skills, and now workflows — and restore it elsewhere. Before these PRs, if you exported a company package, you'd get the agent definitions and skill assignments but not the workflow definitions. A company that relied heavily on ADK pipelines couldn't be fully migrated or duplicated.&lt;/p&gt;

&lt;p&gt;With workflows included in the export/import surface, the company package is again complete. Workflow directories (the Python files that define each pipeline) are bundled alongside the metadata, and the import logic reconstructs them correctly on the receiving end.&lt;/p&gt;




&lt;h2&gt;
  
  
  Observability: Prompt Templates and Graph Analysis
&lt;/h2&gt;

&lt;p&gt;The final two weeks of June focused on making the workflow surface more useful for operators who didn't write the pipeline themselves.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/111" rel="noopener noreferrer"&gt;PR #111&lt;/a&gt; added workflow-scoped prompt templates to the workflow detail page. This is a small but sharp change: rather than showing generic prompt suggestions that apply to any issue, the workflow page now surfaces suggestions that are specific to the workflow's purpose — derived from the workflow record itself. An operator running a data analysis pipeline sees suggestions relevant to that pipeline, not to the agent system in general.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/112" rel="noopener noreferrer"&gt;PR #112&lt;/a&gt; polished the run history UI. The workflow detail page lists all past runs for a workflow. Before this PR, selecting a run from history didn't correctly update the detail view — you'd click a past run and see stale data from the most recent run. The fix ensured that selecting a run from history locks the view to that run's graph, console output, and deliverables, making the history pane a genuine audit trail rather than a misleading navigation element.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/113" rel="noopener noreferrer"&gt;PR #113&lt;/a&gt;, merged on June 18, substantially expanded the pipeline graph analysis. The original renderer had limited understanding of ADK's graph model. This PR added explicit parsing of &lt;code&gt;Workflow&lt;/code&gt; and &lt;code&gt;JoinNode&lt;/code&gt; constructs along with correct DAG edge construction, so the topology renders accurately for real-world pipelines: you can see where branches split, where they converge at join steps, and how the full directed graph of phases is connected — not just a linear sequence of nodes.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Design Decision Worth Unpacking
&lt;/h2&gt;

&lt;p&gt;The most important decision in the Workflows launch is the one that isn't loudly stated: &lt;strong&gt;Workflows is not a subtype of Issues.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It would have been simpler, in some ways, to model workflows as a special issue kind — one with a multi-step execution plan, child issues for each step, and an execution policy that sequences them. Some orchestration platforms take exactly this approach.&lt;/p&gt;

&lt;p&gt;Bizbox didn't. Workflows have their own table, their own API namespace, their own run record type. Issues and workflows are siblings in the company data model, not parent and child.&lt;/p&gt;

&lt;p&gt;The reason is execution fidelity. Issues are designed to be interruptible. An agent checks out an issue, does some work, posts a comment, and exits. The next heartbeat, another agent (or the same one) picks it up. That model requires that the work state lives in comments and documents, not in process memory. It works because the work is fundamentally discrete.&lt;/p&gt;

&lt;p&gt;ADK workflows are not discrete in that sense. A pipeline has local state that must persist across phases — intermediate computations, in-flight API results, the position in the graph. The ADK runtime maintains this state in the Python process. Forcing that into the issue heartbeat model would require serializing and deserializing ADK process state on every heartbeat boundary, which is both complex and fragile.&lt;/p&gt;

&lt;p&gt;By keeping Workflows separate, Bizbox preserves the issue model's simplicity while giving the ADK runtime the long-running execution environment it actually needs. The awaiting-human bridge is where the two worlds meet: when a workflow needs human input, it routes that request through the same provider-agnostic bridge that issues use, so the operator experience is consistent even though the underlying execution model is different.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Still Open
&lt;/h2&gt;

&lt;p&gt;The Workflows platform shipped quickly, which means a few things are still rough.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow scheduling&lt;/strong&gt; isn't built yet. You can trigger a workflow manually through the API or UI, and routines can trigger them, but there's no first-class cron support for workflows. The workaround is a routine that calls the workflow API, which works but adds indirection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-agent workflow steps&lt;/strong&gt; are ADK-native (ADK supports multi-agent graphs), but the Bizbox graph renderer currently assumes a single-agent pipeline topology. Complex multi-agent graphs may not render correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow versioning&lt;/strong&gt; is implicit. The workflow definition is a Python file stored in the company package. If you change it and the change breaks a running pipeline, there's no rollback mechanism in the current design.&lt;/p&gt;




&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;The June 2026 Workflows sprint is one of the cleaner examples of a new primitive done right: a full vertical slice on day one, followed by focused iteration that filled in portability, observability, and operational polish. The design choice to keep Workflows separate from Issues rather than layering on top of them reflects a clear-eyed view of what each model is actually good at.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;input()&lt;/code&gt; bridge is the detail worth remembering. It's a small thing — a monkey-patch — but it expresses the right philosophy: workflow authors write standard Python, Bizbox instruments the execution environment, and the operator experience is consistent because the bridge handles the coordination. The primitive is doing its job when you can't see it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have questions or want to discuss the Workflows architecture? Join the conversation in our &lt;a href="https://github.com/zesthq/bizbox/discussions" rel="noopener noreferrer"&gt;GitHub Discussions&lt;/a&gt; or on &lt;a href="https://community.bizbox.dev" rel="noopener noreferrer"&gt;Discourse&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>architecture</category>
      <category>automation</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Bizbox Build Log — Week of 2026-06-07</title>
      <dc:creator>Bizbox</dc:creator>
      <pubDate>Fri, 12 Jun 2026 04:25:55 +0000</pubDate>
      <link>https://dev.to/joincitro/bizbox-build-log-week-of-2026-06-07-1d20</link>
      <guid>https://dev.to/joincitro/bizbox-build-log-week-of-2026-06-07-1d20</guid>
      <description>&lt;h1&gt;
  
  
  Bizbox Build Log — Week of 2026-06-07
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;The Build Log is a weekly snapshot of what the Bizbox team shipped, decided, traded off, and is still wrestling with. It's written for developers building on Bizbox — no marketing gloss.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Activity covered: June 1–7, 2026 · Published: June 12, 2026&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Shipped this week
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🟢 Workflows platform: human-in-the-loop is live
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Release v2026.605.0 · v2026.603.0&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The big story this cycle is the Workflows primitive reaching its first complete end-to-end state. Two weeks of work landed almost back-to-back:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/86" rel="noopener noreferrer"&gt;PR #86&lt;/a&gt; — Company-scoped Workflows with ADK pipeline runs&lt;/strong&gt; &lt;em&gt;(DennisDenuto)&lt;/em&gt;&lt;br&gt;
Workflows are now a first-class company primitive in Bizbox — separate from issues and routines. Each Workflow maps to a Google ADK pipeline. The runtime records individual runs, tracks live phase state as a renderable graph, gates human handoffs, and persists deliverables. Database schema, API routes, and JWT-protected runtime callbacks all shipped together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/91" rel="noopener noreferrer"&gt;PR #91&lt;/a&gt; — Workflow handoff to ClickUp&lt;/strong&gt; &lt;em&gt;(angelofallars)&lt;/em&gt;&lt;br&gt;
This is the "last mile" for interactive Workflows. When ADK Python code calls &lt;code&gt;input()&lt;/code&gt;, Bizbox now intercepts that call and routes the prompt to a human via ClickUp. The run parks itself and waits. When the human replies, the pipeline resumes. Two fixes came along for the ride: the &lt;code&gt;input()&lt;/code&gt; monkey-patch is now portable across Python environments (an edge case that was quietly breaking some pipelines), and failed workflow runs no longer submit deliverables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/93" rel="noopener noreferrer"&gt;PR #93&lt;/a&gt; — Top-level docs updated for Workflows + Google ADK&lt;/strong&gt; &lt;em&gt;(ralphbibera)&lt;/em&gt;&lt;br&gt;
README, PRODUCT, and SPEC now reflect shipped reality: Workflows surface, Google ADK adapter, and the expanded company model. ADK is in the Works With table. This is a maintenance merge but it matters — the docs were lagging behind the code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/87" rel="noopener noreferrer"&gt;PR #87&lt;/a&gt; — &lt;code&gt;fix(google-adk): strip frontmatter from AGENTS.md instructions&lt;/code&gt;&lt;/strong&gt; &lt;em&gt;(ralphbibera)&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Release v2026.602.1&lt;/strong&gt;&lt;br&gt;
The Google ADK adapter was passing raw YAML frontmatter directly to &lt;code&gt;adk run&lt;/code&gt;, causing it to exit with an invalid input error. Fixed by stripping everything above the first &lt;code&gt;---&lt;/code&gt; fence before the instructions are handed to the adapter. Real breakage fixed silently — this one was happening in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/88" rel="noopener noreferrer"&gt;PR #88&lt;/a&gt; — &lt;code&gt;Enhance issue origin handling with deduplication and tasks&lt;/code&gt;&lt;/strong&gt; &lt;em&gt;(adPalafox)&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Release v2026.602.0&lt;/strong&gt;&lt;br&gt;
Added SHA-256 fingerprint deduplication for suggested-task bundles. Without this, replaying or resubmitting a suggested-task payload would create duplicate child issues. Now it's idempotent.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔧 Fix: ClickUp test link was missing the company slug
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/95" rel="noopener noreferrer"&gt;PR #95&lt;/a&gt;&lt;/strong&gt; &lt;em&gt;(ralphbibera)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The "test connection" button on the ClickUp awaiting-human settings page was generating a link without the company slug. That meant the test notification landed nowhere useful. Fixed at the route level. Regression test added.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Not yet in a tagged release — expect this to ship in the next canary cut (blocked on the canary CI failure detailed below).&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Decisions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Workflows are a separate primitive, not an extension of routines or issues.&lt;/strong&gt;&lt;br&gt;
This was a deliberate design choice in PR #86. Routines are recurring scheduled tasks; issues are discrete work items. Workflows are something different: multi-step ADK pipelines with phases, human gates, and deliverables. Keeping them separate means the data model stays clean and the UI can render them distinctly. The trade-off is more surface area to maintain and a steeper learning curve for users who ask "when do I use a routine vs. a workflow?" &lt;em&gt;(ADR to follow.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;input()&lt;/code&gt; interception as the handoff mechanism.&lt;/strong&gt;&lt;br&gt;
PR #91 chose to intercept Python's &lt;code&gt;input()&lt;/code&gt; rather than require ADK workflows to call a Bizbox-specific SDK function. The rationale is ergonomics: existing ADK pipeline code "just works" without modification. The cost is that &lt;code&gt;input()&lt;/code&gt; monkey-patching is fragile — different Python environments initialise the builtins module at different points, which is why a portability fix shipped in the same PR. See &lt;a href="https://github.com/zesthq/bizbox/blob/master/docs/adr/0001-awaiting-human-bridge.md" rel="noopener noreferrer"&gt;ADR 0001 — awaiting-human bridge&lt;/a&gt; for the bridge lifecycle, adapter registry, and runner/adapter split; a narrower ADR covering the &lt;code&gt;input()&lt;/code&gt; interception mechanism specifically is to follow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Trade-offs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Monkey-patching &lt;code&gt;input()&lt;/code&gt; across Python environments.&lt;/strong&gt;&lt;br&gt;
The fix in PR #91 addressed the known portability gap, but monkey-patching builtins is inherently brittle. If an ADK workflow uses &lt;code&gt;input()&lt;/code&gt; in a subprocess or a thread before the patch lands, the intercept won't fire and the pipeline will block silently. This is a known risk the team is holding — the alternative (a first-party SDK call) would require ADK pipeline authors to change their code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflows ship without retry policies.&lt;/strong&gt;&lt;br&gt;
PR #86's first cut does not include retry semantics for failed pipeline phases. If a phase errors out, the run fails. Whether that's the right default (fail fast) or a gap (users expect retry) is something the team is watching in early usage. Open issue: what's the right automatic retry behaviour for a human-gated phase that times out?&lt;/p&gt;




&lt;h2&gt;
  
  
  Open challenges
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;⚠️ Canary publish CI failure on master (June 5)&lt;/strong&gt;&lt;br&gt;
The &lt;code&gt;Release&lt;/code&gt; workflow's &lt;code&gt;publish_canary&lt;/code&gt; step failed after the PR #95 merge (&lt;a href="https://github.com/zesthq/bizbox/actions/runs/26999915272" rel="noopener noreferrer"&gt;run #26999915272&lt;/a&gt;). Docker build and lockfile refresh succeeded on the same run. The root cause isn't surfaced in the job logs accessible via API. &lt;strong&gt;This is blocking the canary release of PR #95.&lt;/strong&gt; The team needs to triage this before the next cut.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PR #96 — Improve workflow ClickUp handoff lifecycle&lt;/strong&gt; &lt;em&gt;(shipped post-cutoff)&lt;/em&gt;&lt;br&gt;
When a Workflow times out or is interrupted mid-handoff, the ClickUp prompt was still showing a success reaction — making it look alive to the human on the other end. &lt;a href="https://github.com/zesthq/bizbox/pull/96" rel="noopener noreferrer"&gt;PR #96&lt;/a&gt; (cerkiner) fixes the cleanup path so termination closes the ClickUp side too. &lt;em&gt;Merged June 10 — after the June 1–7 coverage window; full coverage in next week's Build Log.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PR #90 — Reviewer routing in ClickUp approval flows&lt;/strong&gt; &lt;em&gt;(shipped post-cutoff)&lt;/em&gt;&lt;br&gt;
&lt;a href="https://github.com/zesthq/bizbox/pull/90" rel="noopener noreferrer"&gt;PR #90&lt;/a&gt; (adPalafox) adds per-company primary and secondary reviewer IDs to the ClickUp awaiting-human approval context. This is important for teams with dedicated approvers — right now every handoff goes to a generic channel. &lt;em&gt;Merged June 9 — after the June 1–7 coverage window; full coverage in next week's Build Log.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built on &lt;a href="https://github.com/zesthq/bizbox" rel="noopener noreferrer"&gt;&lt;code&gt;zesthq/bizbox&lt;/code&gt;&lt;/a&gt; · Releases &lt;a href="https://github.com/zesthq/bizbox/releases/tag/v2026.602.0" rel="noopener noreferrer"&gt;v2026.602.0&lt;/a&gt;, &lt;a href="https://github.com/zesthq/bizbox/releases/tag/v2026.602.1" rel="noopener noreferrer"&gt;v2026.602.1&lt;/a&gt;, &lt;a href="https://github.com/zesthq/bizbox/releases/tag/v2026.603.0" rel="noopener noreferrer"&gt;v2026.603.0&lt;/a&gt; and &lt;a href="https://github.com/zesthq/bizbox/releases/tag/v2026.605.0" rel="noopener noreferrer"&gt;v2026.605.0&lt;/a&gt; · &lt;a href="https://github.com/zesthq/bizbox/pulls" rel="noopener noreferrer"&gt;All open PRs&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Release labels follow the scheme &lt;code&gt;vYYYY.MMDD.patch&lt;/code&gt; — e.g. &lt;code&gt;v2026.605.0&lt;/code&gt; = first cut on June 5, 2026.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>devjournal</category>
      <category>showdev</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Bizbox Build Log — Week of 2026-05-31</title>
      <dc:creator>Bizbox</dc:creator>
      <pubDate>Wed, 10 Jun 2026 23:24:25 +0000</pubDate>
      <link>https://dev.to/joincitro/bizbox-build-log-week-of-2026-05-31-57cg</link>
      <guid>https://dev.to/joincitro/bizbox-build-log-week-of-2026-05-31-57cg</guid>
      <description>&lt;h1&gt;
  
  
  Bizbox Build Log — Week of 2026-05-31
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Headline:&lt;/strong&gt; Two big bets landed in the same week — Workflows arrived as a proper first-class primitive, and the ClickUp human-approval loop closed end-to-end. The pieces are all there; now we stabilise.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is your weekly look at everything that shipped, the choices we made, the trade-offs we accepted, and the things we're still wrestling with. Pull up a chair.&lt;/p&gt;




&lt;h2&gt;
  
  
  Shipped this week
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Workflows are now a first-class Bizbox primitive — &lt;a href="https://github.com/zesthq/bizbox/pull/86" rel="noopener noreferrer"&gt;PR #86&lt;/a&gt; · v2026.603.0
&lt;/h3&gt;

&lt;p&gt;The biggest drop this week. @DennisDenuto landed Workflows as a company-scoped concept that sits alongside issues and routines — not shoehorned into either. What that means in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google ADK-backed execution&lt;/strong&gt; — workflow pipelines run as ADK agents, with phase state persisted as run records.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human handoffs baked in&lt;/strong&gt; — pipelines can pause and wait for a human before resuming.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deliverables that survive&lt;/strong&gt; — artefacts from each run are persisted and surfaced in the UI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A pipeline graph in the UI&lt;/strong&gt; — topologically ordered, showing live phase state and console output.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the foundation. More on what we can build on top of it below.&lt;/p&gt;




&lt;h3&gt;
  
  
  Workflow human-handoffs now route through ClickUp — &lt;a href="https://github.com/zesthq/bizbox/pull/91" rel="noopener noreferrer"&gt;PR #91&lt;/a&gt; · v2026.605.0
&lt;/h3&gt;

&lt;p&gt;The day after Workflows landed, @angelofallars wired up the last kilometre: when ADK Python code calls &lt;code&gt;input()&lt;/code&gt; inside a pipeline, Bizbox now intercepts that call and sends a ClickUp message to collect the human reply — instead of blocking the process forever. A few things that were fixed along the way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;input()&lt;/code&gt; monkey-patching now works consistently across Python environments (was silently failing in some setups).&lt;/li&gt;
&lt;li&gt;Failed workflow runs no longer submit deliverables. You only see artefacts from runs that actually completed.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  ClickUp awaiting-human bridge adapter ships as a pure plugin — &lt;a href="https://github.com/zesthq/bizbox/pull/78" rel="noopener noreferrer"&gt;PR #78&lt;/a&gt; · v2026.601.0
&lt;/h3&gt;

&lt;p&gt;This one technically crossed the line on the last day of May (23:56 UTC, 31 May), so it's in scope. @ralphbibera ported the ClickUp transport and adapter as a genuine plugin — implementing the &lt;code&gt;AwaitingHumanBridgeAdapter&lt;/code&gt; registry interface — without touching bridge core at all.&lt;/p&gt;

&lt;p&gt;What that gives you: ClickUp works through the same provider-agnostic layer as any future provider (Slack, Discord, whatever comes next). The core doesn't know ClickUp exists.&lt;/p&gt;

&lt;p&gt;Included: send/poll/reaction transport, message templates for &lt;code&gt;request_confirmation&lt;/code&gt; and &lt;code&gt;ask_user_questions&lt;/code&gt; interactions, &lt;code&gt;brain_is_thinking&lt;/code&gt; reactions while waiting, terminal &lt;code&gt;✅&lt;/code&gt; / &lt;code&gt;❌&lt;/code&gt; reactions on resolution, and full test coverage.&lt;/p&gt;




&lt;h3&gt;
  
  
  Google ADK instructions no longer ship YAML frontmatter — &lt;a href="https://github.com/zesthq/bizbox/pull/87" rel="noopener noreferrer"&gt;PR #87&lt;/a&gt; · v2026.602.1
&lt;/h3&gt;

&lt;p&gt;A quiet but important fix. &lt;code&gt;AGENTS.md&lt;/code&gt; uses YAML frontmatter for metadata and discovery. That frontmatter was leaking into the instruction payload passed to the Google ADK runtime — producing malformed inputs. @ralphbibera stripped it at the adapter layer. If you were seeing odd ADK behaviour this week, this was probably it.&lt;/p&gt;




&lt;h3&gt;
  
  
  Suggested task deduplication — &lt;a href="https://github.com/zesthq/bizbox/pull/88" rel="noopener noreferrer"&gt;PR #88&lt;/a&gt; · v2026.602.0
&lt;/h3&gt;

&lt;p&gt;@adPalafox fixed a subtle papercut: accepting the same suggested task bundle more than once used to create duplicate child issues. Now the system fingerprints each bundle and reuses existing child issues on repeat accepts. Test coverage included.&lt;/p&gt;




&lt;h3&gt;
  
  
  CI now uses runner Chrome for Playwright — &lt;a href="https://github.com/zesthq/bizbox/pull/84" rel="noopener noreferrer"&gt;PR #84&lt;/a&gt; · v2026.601.0
&lt;/h3&gt;

&lt;p&gt;CI was timing out on headless browser jobs because Playwright was downloading its own browser binary mid-run. @ralphbibera switched to the pre-installed Chrome on the runner — same coverage, less flakiness. Mirrors what upstream Paperclip did in their PR #6967.&lt;/p&gt;




&lt;h3&gt;
  
  
  Docs refreshed for Workflows and Google ADK — &lt;a href="https://github.com/zesthq/bizbox/pull/93" rel="noopener noreferrer"&gt;PR #93&lt;/a&gt; · v2026.605.0
&lt;/h3&gt;

&lt;p&gt;Top-level documentation updated to reflect the new Workflows primitive and Google ADK adapter support. If you've been pointing people at the docs for onboarding, give them a refresh.&lt;/p&gt;




&lt;h3&gt;
  
  
  June 2026 Monthly Deep Dive draft merged — &lt;a href="https://github.com/zesthq/bizbox/pull/83" rel="noopener noreferrer"&gt;PR #83&lt;/a&gt; · v2026.602.0
&lt;/h3&gt;

&lt;p&gt;@adPalafox merged the June Deep Dive draft covering the full story of how the awaiting-human bridge evolved from ClickUp polling to a provider-agnostic approval layer. It's at &lt;code&gt;community/deep-dives/2026-06.md&lt;/code&gt; in the repo and going through the review chain now.&lt;/p&gt;




&lt;h2&gt;
  
  
  Releases
&lt;/h2&gt;

&lt;p&gt;Five releases cut this week:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Notable&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;v2026.601.0&lt;/td&gt;
&lt;td&gt;2026-06-01&lt;/td&gt;
&lt;td&gt;Awaiting-human bridge config, retry/dedupe, Google ADK adapter, ClickUp plugin, CI Chrome fix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v2026.602.0&lt;/td&gt;
&lt;td&gt;2026-06-02&lt;/td&gt;
&lt;td&gt;Suggested task deduplication, June Deep Dive docs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v2026.602.1&lt;/td&gt;
&lt;td&gt;2026-06-02&lt;/td&gt;
&lt;td&gt;Fix: strip AGENTS.md frontmatter for ADK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v2026.603.0&lt;/td&gt;
&lt;td&gt;2026-06-03&lt;/td&gt;
&lt;td&gt;Workflows first-class primitive + ADK pipeline runs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v2026.605.0&lt;/td&gt;
&lt;td&gt;2026-06-05&lt;/td&gt;
&lt;td&gt;Workflow ClickUp handoff, fixed input() patching, docs refresh&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Decisions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Workflows as a separate primitive, not an extension of issues or routines.&lt;/strong&gt;&lt;br&gt;
The team chose to introduce &lt;code&gt;Workflow&lt;/code&gt; as its own company-scoped entity rather than layering pipeline semantics onto existing issue or routine concepts. The call: pipeline graphs, multi-phase execution, and deliverable persistence don't map cleanly onto the issue lifecycle or cron-triggered routines. A clean new primitive was worth the added surface area.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bridge core stays provider-agnostic; adapters register via the registry.&lt;/strong&gt;&lt;br&gt;
When the ClickUp awaiting-human bridge was first developed, ClickUp was hardcoded into core files. That approach was explicitly invalidated before this week: the strict rule is that bridge core must not know about any transport. ClickUp (and any future providers) plug in through &lt;code&gt;AwaitingHumanBridgeAdapter&lt;/code&gt;. The ClickUp plugin was rewritten from scratch to honour this constraint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failed workflow runs must not produce deliverables.&lt;/strong&gt;&lt;br&gt;
Deliverables from a failed run are ambiguous and likely misleading. The decision was to suppress them entirely — a run must complete successfully to submit artefacts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Monkey-patch &lt;code&gt;input()&lt;/code&gt; at the ADK layer for human handoffs.&lt;/strong&gt;&lt;br&gt;
Rather than requiring ADK pipeline authors to use a custom API for human prompts, the team intercepts the standard Python &lt;code&gt;input()&lt;/code&gt; call. This keeps pipeline code idiomatic. The risk (cross-environment patching reliability) was accepted and addressed with the fix in PR #91.&lt;/p&gt;




&lt;h2&gt;
  
  
  Trade-offs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Plugin registration is explicit — it doesn't auto-discover.&lt;/strong&gt;&lt;br&gt;
The ClickUp adapter has to be registered in &lt;code&gt;server/src/index.ts&lt;/code&gt; after external adapter loading completes. This is intentional (predictable startup order, no magic) but means adding a new transport always requires a code change in that file. A future auto-discovery mechanism would remove the friction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ADK &lt;code&gt;input()&lt;/code&gt; patching is fragile by nature.&lt;/strong&gt;&lt;br&gt;
Monkey-patching works — and the cross-environment edge cases are now fixed — but it's still a low-level override that could break if ADK changes how it invokes user code. The team accepted this because the alternative (requiring explicit API calls in every pipeline) hurts adoption. Monitoring is the safeguard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow as a new primitive increases product surface area.&lt;/strong&gt;&lt;br&gt;
More primitives mean more concepts for users to learn. The team weighed this against the complexity of extending issues/routines and chose clarity over brevity. Whether the new primitive surface makes sense to users will surface in community questions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Release CI pipeline gate is currently broken (see Open Challenges).&lt;/strong&gt;&lt;br&gt;
Releases were still published this week despite repeated Release CI failures on master. At some point, bypassing the gate becomes a risk if a bad build slips through. This is an accepted short-term state while the root cause is investigated.&lt;/p&gt;




&lt;h2&gt;
  
  
  Open challenges
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;🔴 Release CI failing on master — eight consecutive failures spanning all five releases&lt;/strong&gt;&lt;br&gt;
The Release workflow has failed on every master merge this week — eight consecutive failures spanning all five releases (v2026.601.0 through v2026.605.0). The regression appears to predate this week; root cause is not yet confirmed. Releases were published despite each failure. This is a significant signal: if the release gate is routinely bypassed, a bad build could slip through. If you're looking for a high-impact investigation, this is it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🟡 PR #90 — Reviewer routing for ClickUp approval handoffs is drafted but stalled&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/zesthq/bizbox/pull/90" rel="noopener noreferrer"&gt;PR #90&lt;/a&gt; adds &lt;code&gt;primaryReviewerUserId&lt;/code&gt; and &lt;code&gt;secondaryReviewerUserId&lt;/code&gt; to the ClickUp awaiting-human approval flow, enabling named reviewer mentions in outbound notifications. It's drafted but CI is failing on the &lt;code&gt;feat-approval-scheme&lt;/code&gt; branch. The feature is needed for any team using named approvers in ClickUp workflows. Blocked until CI is green.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🟡 Pre-existing test failures: agent-permissions and company-portability routes&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;agent-permissions-routes.test.ts&lt;/code&gt; is reporting &lt;code&gt;socket hang up&lt;/code&gt;, and &lt;code&gt;company-portability-routes.test.ts&lt;/code&gt; is returning &lt;code&gt;200&lt;/code&gt; where &lt;code&gt;403&lt;/code&gt; is expected. Both were called out as pre-existing in PR #78. They're not new this week, but they're unresolved and they add noise to every CI run. Someone should own a fix.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Build Log produced from GitHub API data for zesthq/bizbox, 2026-05-31 → 2026-06-06. 8 PRs merged, 5 releases.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>buildinpublic</category>
      <category>devjournal</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Deep Dive: Building the Awaiting-Human Bridge — From ClickUp Polling to a Provider-Agnostic Approval Layer</title>
      <dc:creator>Bizbox</dc:creator>
      <pubDate>Mon, 01 Jun 2026 05:26:22 +0000</pubDate>
      <link>https://dev.to/joincitro/deep-dive-building-the-awaiting-human-bridge-from-clickup-polling-to-a-provider-agnostic-5dm4</link>
      <guid>https://dev.to/joincitro/deep-dive-building-the-awaiting-human-bridge-from-clickup-polling-to-a-provider-agnostic-5dm4</guid>
      <description>&lt;h1&gt;
  
  
  Deep Dive: Building the Awaiting-Human Bridge — From ClickUp Polling to a Provider-Agnostic Approval Layer
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;June 2026&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Background: The Status That Needed a Bridge
&lt;/h2&gt;

&lt;p&gt;In May 2026, we shipped the &lt;code&gt;awaiting_human&lt;/code&gt; status — a dedicated state for issues parked on a human decision, distinct from &lt;code&gt;blocked&lt;/code&gt; (which is for dependency-blocked work that agents can help unstick). If you missed that post, the short version: when an agent creates a &lt;code&gt;request_confirmation&lt;/code&gt; or &lt;code&gt;ask_user_questions&lt;/code&gt; interaction on an &lt;code&gt;in_progress&lt;/code&gt; issue, Bizbox auto-parks the issue to &lt;code&gt;awaiting_human&lt;/code&gt; and prevents agents from acting on it until a human responds.&lt;/p&gt;

&lt;p&gt;That was the right design. But it immediately raised a practical question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does the human actually respond?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In a zero-human company, the "board" isn't sitting in a Bizbox tab watching for notifications. They're in ClickUp, Slack, or wherever their team already lives. If the approval signal has to come through a Bizbox UI action, you've just added a context-switch tax to every human decision point — and in a system designed to reduce human toil, that's a problem.&lt;/p&gt;

&lt;p&gt;The answer we built over the second half of May 2026 is the &lt;strong&gt;awaiting-human bridge&lt;/strong&gt;: a pluggable layer that lets Bizbox send approval requests to external channels and poll for responses, closing the loop without requiring the human to leave their existing workflow.&lt;/p&gt;

&lt;p&gt;This post walks through how we built it, the design decisions we made along the way, and where it's headed.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem in Detail
&lt;/h2&gt;

&lt;p&gt;When an issue enters &lt;code&gt;awaiting_human&lt;/code&gt;, Bizbox needs to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Notify&lt;/strong&gt; the right human in the right channel that a decision is needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wait&lt;/strong&gt; for a response — which might be a reply, a reaction, or a structured approval action.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interpret&lt;/strong&gt; that response correctly: is a thumbs-up an approval? Is a plain text reply a rejection, a question, or just an acknowledgement?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resume&lt;/strong&gt; the agent workflow once the decision is made.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each of these steps has failure modes. Notifications can fail to deliver. Responses can be ambiguous. The same external event can arrive multiple times (webhooks are not exactly-once). And the human might respond days later, after the system has restarted or the bridge state has been garbage-collected.&lt;/p&gt;

&lt;p&gt;We needed a design that was reliable, idempotent, and extensible — because ClickUp is the first channel, but it won't be the last.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture: Four Layers
&lt;/h2&gt;

&lt;p&gt;The bridge architecture that emerged across PRs &lt;a href="https://github.com/zesthq/bizbox/pull/42" rel="noopener noreferrer"&gt;#42&lt;/a&gt;, &lt;a href="https://github.com/zesthq/bizbox/pull/52" rel="noopener noreferrer"&gt;#52&lt;/a&gt;, &lt;a href="https://github.com/zesthq/bizbox/pull/56" rel="noopener noreferrer"&gt;#56&lt;/a&gt;, &lt;a href="https://github.com/zesthq/bizbox/pull/65" rel="noopener noreferrer"&gt;#65&lt;/a&gt;, &lt;a href="https://github.com/zesthq/bizbox/pull/68" rel="noopener noreferrer"&gt;#68&lt;/a&gt;, &lt;a href="https://github.com/zesthq/bizbox/pull/70" rel="noopener noreferrer"&gt;#70&lt;/a&gt;, &lt;a href="https://github.com/zesthq/bizbox/pull/74" rel="noopener noreferrer"&gt;#74&lt;/a&gt;, and &lt;a href="https://github.com/zesthq/bizbox/pull/76" rel="noopener noreferrer"&gt;#76&lt;/a&gt; has four distinct layers:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Outbox (Reliable Notification Delivery)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/56" rel="noopener noreferrer"&gt;PR #56&lt;/a&gt;&lt;/strong&gt; introduced the &lt;code&gt;awaiting_human_notification_outbox&lt;/code&gt; table — a durable queue for outbound notifications. Instead of firing-and-forgetting a ClickUp message, Bizbox writes a row to the outbox first, then a background processor picks it up, delivers it, and records the resulting ClickUp message ID.&lt;/p&gt;

&lt;p&gt;This gives us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Retryability:&lt;/strong&gt; If the ClickUp API is down, the notification retries on the next heartbeat cycle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deduplication:&lt;/strong&gt; The outbox row has a &lt;code&gt;dedupeKey&lt;/code&gt; tied to the issue and interaction, so we never send the same notification twice even if the trigger fires multiple times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auditability:&lt;/strong&gt; Every notification attempt, success, and failure is logged with timestamps and error details.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The outbox pattern is a classic reliability primitive, but it's worth calling out explicitly: this is the foundation that makes everything else safe to build on.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Approval Polling Loop
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/42" rel="noopener noreferrer"&gt;PR #42&lt;/a&gt;&lt;/strong&gt; added the first version of ClickUp approval polling. On each heartbeat cycle, for every &lt;code&gt;awaiting_human&lt;/code&gt; issue with a pending &lt;code&gt;request_confirmation&lt;/code&gt; interaction, Bizbox polls the ClickUp message thread for replies and reactions.&lt;/p&gt;

&lt;p&gt;The initial design was straightforward: if a configured positive reply or reaction is detected, resolve the interaction as approved and wake the assignee agent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/52" rel="noopener noreferrer"&gt;PR #52&lt;/a&gt;&lt;/strong&gt; cleaned up two reliability issues that surfaced early in production. First, ClickUp comment IDs can arrive as numbers rather than strings — the adapter was only accepting strings, which caused valid top-level comments and replies to be silently dropped during import. PR #52 aligned the adapter with the existing scalar-ID coercion pattern used elsewhere in the codebase. Second, a bridge status value (&lt;code&gt;agent_replied&lt;/code&gt;) existed in types and UI filtering but had no runtime transition path — it was unreachable dead code. Removing it simplified the bridge state machine and eliminated a source of confusion when reading bridge lifecycle logs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/68" rel="noopener noreferrer"&gt;PR #68&lt;/a&gt;&lt;/strong&gt; hardened the message ID resolution. The polling loop needs the ClickUp message ID to know which thread to poll — but there's a race condition: the activity log entry (which stores the message ID) might be written before the outbox processor has actually delivered the notification. PR #68 added a fallback: if the message ID isn't in the activity log, look it up from the outbox table using the &lt;code&gt;dedupeKey&lt;/code&gt;. This eliminated a class of "polling the wrong thread" bugs that showed up in production.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Rejection Semantics
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/70" rel="noopener noreferrer"&gt;PR #70&lt;/a&gt;&lt;/strong&gt; tackled a question that sounds simple but has real behavioral implications: &lt;em&gt;what does a non-approval reply mean?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The initial implementation treated non-approval replies as noise — they were ignored, and the bridge kept waiting. That turned out to be wrong in practice. When a human replies "no, don't do this" or "I need more context first," ignoring that reply leaves the issue parked indefinitely and the agent unaware that the human has weighed in.&lt;/p&gt;

&lt;p&gt;The new behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Explicit negative reactions&lt;/strong&gt; (e.g., &lt;code&gt;thumbsdown&lt;/code&gt;) → immediate rejection, no comment forwarded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-approval text replies&lt;/strong&gt; → treated as rejection, forwarded as a comment on the issue so the agent has context when it wakes up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approval replies/reactions&lt;/strong&gt; → resolve the interaction as approved, wake the agent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes the bridge a two-way channel, not just a one-way approval gate. The human's response — whatever it is — gets back to the agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The Provider-Agnostic Bridge Core
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/65" rel="noopener noreferrer"&gt;PR #65&lt;/a&gt;&lt;/strong&gt; laid the configuration groundwork for the bridge. It introduced dedicated environment variables (&lt;code&gt;CLICKUP_AWAITING_HUMAN_CHANNEL_ID&lt;/code&gt; and &lt;code&gt;CLICKUP_AWAITING_HUMAN_CHANNEL_NAME&lt;/code&gt;) for specifying the ClickUp approval channel, with fallback to legacy engineering variables and a default of &lt;code&gt;bizbox-feed&lt;/code&gt; when no channel name is provided. It also improved the human-facing notification message content — making the approval request clearer and more actionable — and updated &lt;code&gt;.env.example&lt;/code&gt; documentation. This was the first step toward making the bridge channel-configurable rather than hardcoded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/74" rel="noopener noreferrer"&gt;PR #74&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/76" rel="noopener noreferrer"&gt;PR #76&lt;/a&gt;&lt;/strong&gt; are where the architecture shifted from "ClickUp integration" to "bridge infrastructure."&lt;/p&gt;

&lt;p&gt;PR #74 introduced the &lt;code&gt;company_awaiting_human_settings&lt;/code&gt; table and a configuration schema that lets each company specify its own bridge provider and routing. The first supported provider is ClickUp, with workspace and channel routing. But the schema is designed to accommodate future providers without changes to the core.&lt;/p&gt;

&lt;p&gt;PR #76 finalized the bridge lifecycle semantics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Interaction-scoped dedupe.&lt;/strong&gt; Inbound events now deduplicate on &lt;code&gt;(interaction_id, external_event_id)&lt;/code&gt; rather than just &lt;code&gt;external_event_id&lt;/code&gt;. This means the same external event (e.g., a webhook delivered twice) is safely ignored, but the same event arriving for a &lt;em&gt;different&lt;/em&gt; interaction on the same issue is handled correctly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free-text replies stay as comments.&lt;/strong&gt; Plain replies from the human are imported as issue comments and wake the agent, rather than being treated as approval signals. The bridge stays open until an explicit approval or rejection arrives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retries create fresh rows.&lt;/strong&gt; Bridge retries no longer reuse stale state; each retry creates a new outbox row, preventing stale delivery state from blocking future attempts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The ClickUp transport adapter itself is being extracted into a pure plugin in &lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/78" rel="noopener noreferrer"&gt;PR #78&lt;/a&gt;&lt;/strong&gt; (still in review at time of writing), which will keep the bridge core entirely provider-agnostic and let ClickUp register via &lt;code&gt;AwaitingHumanBridgeRegistry&lt;/code&gt; like any future provider.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Design Decisions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Decision 1: Outbox-first, not fire-and-forget
&lt;/h3&gt;

&lt;p&gt;We could have sent ClickUp notifications inline during the issue status transition. It's simpler code. But inline delivery means a ClickUp API failure blocks the status transition, and a retry requires re-running the whole transition logic.&lt;/p&gt;

&lt;p&gt;The outbox decouples delivery from state change. The issue parks to &lt;code&gt;awaiting_human&lt;/code&gt; immediately; the notification goes out when it can. This is the right trade-off for a system where the human-facing notification is important but not on the critical path of the state machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decision 2: Non-approval replies are rejections, not noise
&lt;/h3&gt;

&lt;p&gt;This was the most debated call. The argument for treating non-approval replies as noise: it's simpler, and it avoids false rejections from humans who reply "got it" or "looking now" without intending to reject.&lt;/p&gt;

&lt;p&gt;The argument for treating them as rejections: in a zero-human company, the human's time is the scarce resource. If they've replied, they've engaged. Ignoring their reply and leaving the issue parked is worse than a false rejection — at least a rejection wakes the agent and gives it the human's comment as context.&lt;/p&gt;

&lt;p&gt;We went with rejection-as-default, with the explicit negative reaction path as the "clean" rejection signal. We're watching for false-rejection reports in production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decision 3: Provider-agnostic core from the start
&lt;/h3&gt;

&lt;p&gt;We could have shipped a ClickUp-specific bridge and refactored later. The counter-argument: the bridge touches the database schema, the heartbeat service, and the interaction resolution flow. Refactoring those layers after the fact is expensive and risky.&lt;/p&gt;

&lt;p&gt;By designing the bridge core to be provider-agnostic from PR #74 onward — with ClickUp as the first adapter — we pay a small upfront cost for a much cleaner extension path. When Slack or Discord support lands, it registers via the same &lt;code&gt;AwaitingHumanBridgeRegistry&lt;/code&gt; without touching bridge core.&lt;/p&gt;




&lt;h2&gt;
  
  
  Trade-Offs and Open Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Polling Tax
&lt;/h3&gt;

&lt;p&gt;The current implementation polls ClickUp on every heartbeat cycle for every &lt;code&gt;awaiting_human&lt;/code&gt; issue. At low volume, this is fine. At scale, it's a lot of API calls — and ClickUp's rate limits are not generous.&lt;/p&gt;

&lt;p&gt;We're considering a webhook-first approach where ClickUp pushes events to Bizbox, with polling as a fallback. That requires a publicly reachable webhook endpoint and more complex event routing, but it would dramatically reduce the polling load.&lt;/p&gt;

&lt;h3&gt;
  
  
  Approval Signal Ambiguity
&lt;/h3&gt;

&lt;p&gt;The configured "positive reply" list is a blunt instrument. Right now, operators configure a list of strings (e.g., &lt;code&gt;["yes", "approved", "lgtm"]&lt;/code&gt;) that count as approval. That works for structured workflows but breaks down for natural language responses.&lt;/p&gt;

&lt;p&gt;A future direction: use a lightweight classifier to interpret free-text replies, rather than exact-match string lists. The risk is false positives on ambiguous language — which in an approval context is a meaningful safety concern.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Provider Routing
&lt;/h3&gt;

&lt;p&gt;The current schema supports one bridge provider per company. But some companies might want to route different issue types to different channels — high-priority approvals to a dedicated Slack channel, routine confirmations to ClickUp.&lt;/p&gt;

&lt;p&gt;The settings schema has room for this, but the routing logic isn't there yet. It's on the roadmap.&lt;/p&gt;

&lt;h3&gt;
  
  
  The PR #78 Gap
&lt;/h3&gt;

&lt;p&gt;The ClickUp transport adapter is still in review as a pure plugin (&lt;a href="https://github.com/zesthq/bizbox/pull/78" rel="noopener noreferrer"&gt;PR #78&lt;/a&gt;). Until it merges, the bridge core and the ClickUp adapter are more coupled than the final architecture intends. We're treating this as a known technical debt item with a clear resolution path.&lt;/p&gt;




&lt;h2&gt;
  
  
  What We Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Reliability primitives pay for themselves.&lt;/strong&gt; The outbox pattern added a migration, a background processor, and a handful of service methods. It also eliminated an entire class of "notification never arrived" bugs and made the retry story trivial. Worth it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Behavioral design is harder than technical design.&lt;/strong&gt; The rejection semantics question — what does a non-approval reply mean? — took more discussion than the outbox implementation. The technical work was straightforward; the behavioral contract required careful thought about what the system should do in ambiguous situations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Provider-agnostic from the start is the right call for integration layers.&lt;/strong&gt; The temptation to ship a ClickUp-specific bridge and "clean it up later" is real. The cost of doing it right upfront was one extra PR and a slightly more abstract schema. The benefit is a clean extension path for every future provider.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/78" rel="noopener noreferrer"&gt;PR #78&lt;/a&gt;&lt;/strong&gt; — ClickUp transport as a pure plugin, completing the provider-agnostic bridge architecture.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webhook-first polling&lt;/strong&gt; — reduce the heartbeat polling load by accepting ClickUp push events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-provider routing&lt;/strong&gt; — route different issue types to different approval channels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural language approval interpretation&lt;/strong&gt; — move beyond exact-match string lists for approval signal detection.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building on Bizbox or thinking about how to handle human-in-the-loop approval flows in your own agent systems, we'd love to hear what patterns you're using. Drop a note in &lt;a href="https://github.com/zesthq/bizbox/discussions" rel="noopener noreferrer"&gt;GitHub Discussions&lt;/a&gt; or on &lt;a href="https://bizboxai.discourse.group" rel="noopener noreferrer"&gt;Discourse&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Related Work
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/33" rel="noopener noreferrer"&gt;PR #33: Add &lt;code&gt;awaiting_human&lt;/code&gt; issue status&lt;/a&gt;&lt;/strong&gt; — the status that made the bridge necessary&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/42" rel="noopener noreferrer"&gt;PR #42: ClickUp approval polling&lt;/a&gt;&lt;/strong&gt; — first approval polling implementation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/52" rel="noopener noreferrer"&gt;PR #52: Normalize comment IDs and remove dead bridge status&lt;/a&gt;&lt;/strong&gt; — cleanup and normalization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/56" rel="noopener noreferrer"&gt;PR #56: Awaiting-human notification outbox&lt;/a&gt;&lt;/strong&gt; — reliable notification delivery&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/65" rel="noopener noreferrer"&gt;PR #65: ClickUp approval configuration&lt;/a&gt;&lt;/strong&gt; — company-scoped channel routing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/68" rel="noopener noreferrer"&gt;PR #68: Message ID fallback in heartbeat&lt;/a&gt;&lt;/strong&gt; — race condition fix&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/70" rel="noopener noreferrer"&gt;PR #70: Rejection semantics for non-approval replies&lt;/a&gt;&lt;/strong&gt; — behavioral design decision&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/74" rel="noopener noreferrer"&gt;PR #74: Bridge configuration schema&lt;/a&gt;&lt;/strong&gt; — provider-agnostic settings layer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/76" rel="noopener noreferrer"&gt;PR #76: Bridge retry and reply dedupe&lt;/a&gt;&lt;/strong&gt; — lifecycle hardening&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/pull/78" rel="noopener noreferrer"&gt;PR #78: ClickUp bridge adapter as pure plugin&lt;/a&gt;&lt;/strong&gt; — in review&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/zesthq/bizbox/blob/master/docs/blog/deep-dive-2026-05-awaiting-human.md" rel="noopener noreferrer"&gt;May 2026 Deep Dive: The &lt;code&gt;awaiting_human&lt;/code&gt; Status&lt;/a&gt;&lt;/strong&gt; — the foundation this bridge builds on&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;About Bizbox:&lt;/strong&gt; We're building an AI-native task orchestration system where humans and AI agents collaborate on structured work. This Deep Dive is part of our monthly series on architectural decisions and lessons learned. &lt;a href="https://github.com/zesthq/bizbox" rel="noopener noreferrer"&gt;Follow the project on GitHub.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>architecture</category>
      <category>automation</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Bizbox Build Log — Week of 2026-05-30</title>
      <dc:creator>Bizbox</dc:creator>
      <pubDate>Fri, 29 May 2026 00:06:15 +0000</pubDate>
      <link>https://dev.to/joincitro/bizbox-build-log-week-of-2026-05-30-4n3</link>
      <guid>https://dev.to/joincitro/bizbox-build-log-week-of-2026-05-30-4n3</guid>
      <description>&lt;h1&gt;
  
  
  Bizbox Build Log — Week of 2026-05-30
&lt;/h1&gt;

&lt;p&gt;Five substantive PRs merged this week (2026-05-23 through 2026-05-30), two releases shipped. The theme: the awaiting-human bridge grows up — two merged PRs lay the provider-agnostic infrastructure (company-scoped configuration and hardened lifecycle semantics), with the ClickUp transport adapter still in review. Plus: the first Google ADK agent adapter lands, and the production VMs get a resource bump to match real workloads.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note on release tags: PRs #72, #74, and #76 merged to master on 2026-05-28 and are not yet in a tagged release at time of writing. PRs #70 and #73 shipped in v2026.525.0 and v2026.525.1 respectively.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Shipped This Week
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🤖 Google ADK agent adapter
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;PR &lt;a href="https://github.com/zesthq/bizbox/pull/72" rel="noopener noreferrer"&gt;#72&lt;/a&gt; · @DennisDenuto · merged 2026-05-28 · not yet in a tagged release&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bizbox can now create and manage agents backed by Google's Agent Development Kit (ADK). The new adapter package covers server execution, CLI formatting, stdout parsing, and UI config/build helpers. Google ADK is registered in the shared agent-type registry, adapter registry, and capability lookup — so it behaves like any other built-in adapter from the operator's perspective: create it, configure it, assign it to issues.&lt;/p&gt;

&lt;p&gt;The adapter ships with server-level tests for event parsing and execution behaviour, and the agent loadout UI was updated to include Google ADK in the configuration and new-agent flows.&lt;/p&gt;

&lt;p&gt;This is the first non-OpenClaw adapter to land in the core codebase. It opens the door to multi-runtime agent pipelines where different tasks can be routed to the best-fit execution environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  🌉 Awaiting-human bridge: retry and reply dedupe
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;PR &lt;a href="https://github.com/zesthq/bizbox/pull/76" rel="noopener noreferrer"&gt;#76&lt;/a&gt; · @ralphbibera · merged 2026-05-28 · not yet in a tagged release&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The second of two merged awaiting-human bridge PRs this week (a third, the ClickUp transport adapter PR &lt;a href="https://github.com/zesthq/bizbox/pull/78" rel="noopener noreferrer"&gt;#78&lt;/a&gt;, is still in review). This PR finalises the bridge lifecycle. Key changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Interaction-scoped dedupe.&lt;/strong&gt; Inbound events now deduplicate on &lt;code&gt;(interaction_id, external_event_id)&lt;/code&gt; rather than just &lt;code&gt;external_event_id&lt;/code&gt;. The same external event can be safely ignored across bridge reopenings without false-positive suppression.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free-text replies stay as comments.&lt;/strong&gt; Plain replies from the human operator are now imported as issue comments and wake the agent, rather than being treated as approval signals. The bridge stays open until an explicit approval or rejection arrives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retries create fresh rows.&lt;/strong&gt; Bridge retries no longer reuse stale state; each retry starts clean, which eliminates a class of ghost-approval bugs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Heartbeat compatibility.&lt;/strong&gt; The heartbeat reconciler previously contained a hardcoded &lt;code&gt;clickup-chat&lt;/code&gt; reference for filtering legacy delivered interactions. That reference has been moved into the bridge service, keeping the reconciler provider-agnostic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Migration &lt;code&gt;0076&lt;/code&gt; consolidates the final inbound event schema and dedupe index in one place.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚙️ Awaiting-human bridge: company-scoped configuration
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;PR &lt;a href="https://github.com/zesthq/bizbox/pull/74" rel="noopener noreferrer"&gt;#74&lt;/a&gt; · @ralphbibera · merged 2026-05-28 · not yet in a tagged release&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first of the two merged bridge PRs this week adds the settings layer that makes the bridge multi-tenant. Before this, every company shared the same (or no) external channel for human approvals — settings were hardcoded or absent. Now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A new &lt;code&gt;company_awaiting_human_settings&lt;/code&gt; table (migration &lt;code&gt;0075&lt;/code&gt;) stores per-company provider config as JSONB.&lt;/li&gt;
&lt;li&gt;The first supported provider is ClickUp, with workspace/channel routing and secret rotation.&lt;/li&gt;
&lt;li&gt;Zod validators cover PATCH requests; the &lt;code&gt;awaitingHumanSettingsService&lt;/code&gt; handles CRUD and secret rotation.&lt;/li&gt;
&lt;li&gt;The schema is designed so future providers (Slack, Discord, etc.) can be added without changing the settings shape.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the infrastructure that makes the pure-plugin ClickUp adapter (PR &lt;a href="https://github.com/zesthq/bizbox/pull/78" rel="noopener noreferrer"&gt;#78&lt;/a&gt;, still open) meaningful: each company can now point the bridge at its own ClickUp workspace.&lt;/p&gt;

&lt;h3&gt;
  
  
  🖥️ VM resource upgrade: 4 GB memory, 4 CPUs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;PR &lt;a href="https://github.com/zesthq/bizbox/pull/73" rel="noopener noreferrer"&gt;#73&lt;/a&gt; · v2026.525.1 · @adPalafox · merged 2026-05-25&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both &lt;code&gt;fly.toml&lt;/code&gt; and &lt;code&gt;fly.private.toml&lt;/code&gt; now allocate 4 GB of memory and 4 shared CPUs per VM, up from 2 GB / 2 CPUs. The change reflects real production workloads: multi-agent runs with concurrent heartbeats were hitting memory pressure under the old allocation. The upgrade doubles headroom for parallel execution without changing any application code.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ ClickUp approval: non-approval replies treated as rejection
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;PR &lt;a href="https://github.com/zesthq/bizbox/pull/70" rel="noopener noreferrer"&gt;#70&lt;/a&gt; · v2026.525.0 · @adPalafox · merged 2026-05-25&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The ClickUp awaiting-human approval handler now has explicit semantics for every reply type:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Explicit negative reactions&lt;/strong&gt; (&lt;code&gt;thumbsdown&lt;/code&gt;) immediately reject the interaction — no comment text is forwarded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-approval free-text replies&lt;/strong&gt; are treated as rejections, with the reply text forwarded as a comment into the related issue for context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approval signals&lt;/strong&gt; (positive reactions, explicit approval phrases) continue to work as before.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Previously, a human replying with anything other than an approval phrase could leave the interaction in an ambiguous state. The new behaviour is deterministic: every reply resolves the interaction one way or the other.&lt;/p&gt;




&lt;h2&gt;
  
  
  Decisions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Provider-agnostic bridge architecture.&lt;/strong&gt; The team committed to keeping the awaiting-human bridge core strictly provider-agnostic. PRs #74 and #76 build the infrastructure; PR #78 (still open) ports the ClickUp transport as a pure plugin that registers via &lt;code&gt;AwaitingHumanBridgeRegistry&lt;/code&gt;. The rule: bridge core files must not reference any specific provider. This makes adding Slack, Discord, or any future channel a matter of writing a new adapter, not touching shared infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google ADK as a first-class adapter.&lt;/strong&gt; Rather than treating Google ADK as an experimental or external integration, the team registered it in the same adapter registry and capability lookup as OpenClaw. The decision signals that Bizbox is positioning itself as runtime-agnostic — the orchestration layer, not a wrapper around a single agent runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VM resources doubled proactively.&lt;/strong&gt; The resource bump in PR #73 was driven by observed memory pressure in production, not a planned capacity review. The decision to double both memory and CPUs (rather than a more conservative step-up) reflects a preference for headroom over incremental tuning.&lt;/p&gt;




&lt;h2&gt;
  
  
  Trade-offs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bridge config is company-scoped, not agent-scoped.&lt;/strong&gt; The new &lt;code&gt;company_awaiting_human_settings&lt;/code&gt; table routes all awaiting-human interactions for a company through the same provider and channel. That's the right default for most deployments, but companies that want different approval channels for different agent types or projects will need a future per-agent or per-project override layer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google ADK adapter ships without end-to-end integration tests.&lt;/strong&gt; The PR includes server-level unit tests for event parsing and execution, and UI tests for the loadout editor. A full end-to-end test (agent creation → issue assignment → heartbeat execution → result) is not yet in place. The adapter is functional but the integration surface is less hardened than the OpenClaw adapter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-approval reply semantics are a breaking change for edge cases.&lt;/strong&gt; PR #70 changes what happens when a human replies with free text that isn't an approval phrase. Previously the behaviour was undefined; now it's an explicit rejection. Any workflow that relied on free-text replies being ignored (rather than treated as rejections) will behave differently. The change is correct, but operators should be aware.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Open Challenges
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ClickUp pure-plugin adapter (PR #78) is still open.&lt;/strong&gt; The bridge infrastructure (PRs #74 and #76) is merged, but the ClickUp transport itself is still in review. Until #78 lands, the bridge has the configuration layer but no live ClickUp transport wired to it. The full end-to-end path — company settings → bridge core → ClickUp transport → human reply → agent wake — is not yet closed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bridge reconciliation coverage.&lt;/strong&gt; Two PRs merged to the awaiting-human bridge this week, with a third (PR #78) still in review. The surface is being hardened rapidly, but the full reconciliation path (outbox → ClickUp delivery → heartbeat poll → interaction accept → agent wake) still lacks an end-to-end integration test. This was flagged last week and remains on the backlog.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-runtime agent routing.&lt;/strong&gt; The Google ADK adapter landing opens a real question: how does an operator decide which runtime to use for a given task? Today the choice is made at agent-creation time and is static. Dynamic routing — assigning tasks to the best-fit runtime based on task type, cost, or latency — is not yet designed.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  X Thread Teaser
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;🧵 Bizbox Build Log — Week of May 30, 2026&lt;/p&gt;

&lt;p&gt;5 PRs merged, 2 releases shipped. The awaiting-human bridge got a full architecture upgrade, Google ADK landed as a first-class adapter, and the VMs got a resource bump. Here's what moved 👇&lt;/p&gt;

&lt;p&gt;1/ New: Google ADK agent adapter. Bizbox can now create and run agents backed by Google's Agent Development Kit — registered in the same adapter registry as OpenClaw. First step toward runtime-agnostic orchestration.&lt;br&gt;
&lt;a href="https://github.com/zesthq/bizbox/pull/72" rel="noopener noreferrer"&gt;https://github.com/zesthq/bizbox/pull/72&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2/ Awaiting-human bridge: company-scoped config + lifecycle hardening. Each company can now configure its own approval channel (ClickUp first). Retries create fresh rows, free-text replies stay as comments, inbound events dedupe per interaction.&lt;br&gt;
&lt;a href="https://github.com/zesthq/bizbox/pull/74" rel="noopener noreferrer"&gt;https://github.com/zesthq/bizbox/pull/74&lt;/a&gt; &lt;a href="https://github.com/zesthq/bizbox/pull/76" rel="noopener noreferrer"&gt;https://github.com/zesthq/bizbox/pull/76&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3/ ClickUp approval semantics are now deterministic. Thumbsdown = immediate rejection. Free-text non-approval reply = rejection with context forwarded. No more ambiguous states.&lt;br&gt;
&lt;a href="https://github.com/zesthq/bizbox/pull/70" rel="noopener noreferrer"&gt;https://github.com/zesthq/bizbox/pull/70&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4/ VMs doubled: 4 GB / 4 CPUs. Driven by real memory pressure from concurrent multi-agent heartbeats. Headroom &amp;gt; incremental tuning.&lt;br&gt;
&lt;a href="https://github.com/zesthq/bizbox/pull/73" rel="noopener noreferrer"&gt;https://github.com/zesthq/bizbox/pull/73&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5/ Open challenge: the ClickUp bridge adapter (PR #78) is still in review. The infrastructure is merged but the live transport isn't wired yet. The full approval loop closes when #78 lands.&lt;/p&gt;

&lt;p&gt;Full build log: &lt;a href="https://github.com/zesthq/bizbox/blob/master/community/build-logs/2026-05-30.md" rel="noopener noreferrer"&gt;https://github.com/zesthq/bizbox/blob/master/community/build-logs/2026-05-30.md&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;Grounded in merged PRs and releases from &lt;a href="https://github.com/zesthq/bizbox" rel="noopener noreferrer"&gt;zesthq/bizbox&lt;/a&gt;, 2026-05-23 to 2026-05-30. No activity was invented.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>devjournal</category>
      <category>infrastructure</category>
      <category>softwaredevelopment</category>
    </item>
  </channel>
</rss>
