<?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>Forem: Lin Zhu</title>
    <description>The latest articles on Forem by Lin Zhu (@lin_zhu_c66f7f4c200d3a186).</description>
    <link>https://forem.com/lin_zhu_c66f7f4c200d3a186</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3926034%2F7ef812a4-b446-4792-baa6-313a520e71cb.jpg</url>
      <title>Forem: Lin Zhu</title>
      <link>https://forem.com/lin_zhu_c66f7f4c200d3a186</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/lin_zhu_c66f7f4c200d3a186"/>
    <language>en</language>
    <item>
      <title>Building on Zeeren in 2026: Unified MiniApp Provision, Durable Schedules, and the Composable Skills Layer</title>
      <dc:creator>Lin Zhu</dc:creator>
      <pubDate>Tue, 12 May 2026 14:13:44 +0000</pubDate>
      <link>https://forem.com/lin_zhu_c66f7f4c200d3a186/building-on-zeeren-in-2026-unified-miniapp-provision-durable-schedules-and-the-composable-skills-4146</link>
      <guid>https://forem.com/lin_zhu_c66f7f4c200d3a186/building-on-zeeren-in-2026-unified-miniapp-provision-durable-schedules-and-the-composable-skills-4146</guid>
      <description>&lt;h2&gt;
  
  
  A quick orientation
&lt;/h2&gt;

&lt;p&gt;Zeeren is an agentic overseas-ops platform. The core abstraction is a &lt;strong&gt;Work&lt;/strong&gt; — a persistent, collaborative context that holds a resource tree, runs agent nodes, and owns schedules, MiniApps, and data assets. Think of it like a long-lived project container that agents can read, write, and schedule work into.&lt;/p&gt;

&lt;p&gt;If you're building on top of Zeeren, there are three recent changes worth knowing about.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Unified MiniApp provision: one call instead of 14
&lt;/h2&gt;

&lt;p&gt;The old flow (&lt;code&gt;pre-2026-04&lt;/code&gt;) required chaining 14 discrete API calls to scaffold a MiniApp — create the record, create the resource tree, link the Work, apply migrations, spin the dev container, and more. Any partial failure left you in an inconsistent state.&lt;/p&gt;

&lt;p&gt;The new endpoint, &lt;code&gt;POST /api/v1/miniapps/provision&lt;/code&gt; (gated by &lt;code&gt;MINIAPP_UNIFIED_PROVISION=true&lt;/code&gt;), wraps the entire transaction. One body, one round-trip:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"project-tracker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Project Tracker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"work_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5821&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"stack"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"frontend"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"backend"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python-fastapi"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"runtime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docker"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data_mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tenant_db"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tables"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"projects"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"columns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"nullable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"'open'"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"owner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scope"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tenant"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response comes back with the dev container's &lt;code&gt;host_port&lt;/code&gt;, a live &lt;code&gt;preview_url&lt;/code&gt;, and the materialised workdir path — everything you need to start generating code immediately.&lt;/p&gt;

&lt;p&gt;A few sharp edges worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;SLUG_CONFLICT&lt;/code&gt; (409)&lt;/strong&gt;: append &lt;code&gt;-N&lt;/code&gt; and retry once. The platform won't do this for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;provision_failed&lt;/code&gt; (500)&lt;/strong&gt;: the transaction rolled back cleanly. Same body is safe to retry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;WORK_ALREADY_AUTHORING&lt;/code&gt; (409)&lt;/strong&gt;: don't retry — the Work already has a MiniApp. Call &lt;code&gt;/miniapps/{id}/status&lt;/code&gt; to find where to resume.&lt;/li&gt;
&lt;li&gt;The platform auto-adds &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;created_at&lt;/code&gt;, &lt;code&gt;updated_at&lt;/code&gt;. Don't declare them; you'll get a 422.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The legacy 14-action surface still exists for Works provisioned before April 2026, but new Works should use the unified endpoint.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. WorkSchedules with multi-trigger support
&lt;/h2&gt;

&lt;p&gt;Scheduling in Zeeren is handled through &lt;code&gt;WorkSchedule&lt;/code&gt; records. What's useful is the range of &lt;code&gt;trigger_type&lt;/code&gt; options — it's not just cron:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Trigger type&lt;/th&gt;
&lt;th&gt;When to use it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CRON&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fixed calendar cadence: "every weekday at 9am"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INTERVAL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rolling repeat: "every 5 minutes"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WEBHOOK&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;External system POSTs to a generated endpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EVENT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Internal platform event, e.g. &lt;code&gt;log.error&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CHAT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;When a user DMs a Work with a specific prefix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MQ&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Kafka/message-queue topic subscriber&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;execution_mode&lt;/code&gt; field controls whether each fire opens a new Work (&lt;code&gt;NEW_WORK&lt;/code&gt;) or appends a node to the existing one (&lt;code&gt;APPEND_NODE&lt;/code&gt;). The latter is the right default when you want the schedule's output to stay in the same conversational context as the Work that owns it.&lt;/p&gt;

&lt;p&gt;A minimal CRON body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"owner_scope"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USER"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"owner_work_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;653&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Daily standup digest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"trigger_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CRON"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"trigger_config"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"cron"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0 9 * * 1-5"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"execution_mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"APPEND_NODE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payload_template"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Generate today's standup digest."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"is_active"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For &lt;code&gt;WEBHOOK&lt;/code&gt; triggers, the 201 response includes an &lt;code&gt;hmac_secret_plaintext&lt;/code&gt; that is &lt;strong&gt;not retrievable later&lt;/strong&gt;. Store it on creation.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The skills layer: composable, declarative, skill-card-driven
&lt;/h2&gt;

&lt;p&gt;The thing that ties Work + MiniApp + Schedule together is the &lt;strong&gt;skills layer&lt;/strong&gt;. A skill is a declarative unit (&lt;code&gt;SKILL.md&lt;/code&gt; + optional scripts) that defines inputs, outputs, estimated cost, and a procedure for an agent to follow. Skills compose: a meta-skill like &lt;code&gt;zeeren-overseas-retention&lt;/code&gt; calls &lt;code&gt;zeeren-goal-decomposer&lt;/code&gt;, which fans out into content, concern-triage, and attribution skills.&lt;/p&gt;

&lt;p&gt;From a developer perspective, a skill card looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;brief&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;outputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;channel_drafts&lt;/span&gt;
    &lt;span class="na"&gt;output_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;draft_action&lt;/span&gt;
    &lt;span class="na"&gt;action_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;publish_&amp;lt;channel&amp;gt;_post"&lt;/span&gt;
&lt;span class="na"&gt;estimated_cost_usd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.12&lt;/span&gt;
&lt;span class="na"&gt;estimated_duration_seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;45&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Skills target either a &lt;code&gt;WORK_DOMAIN&lt;/code&gt; agent (flexible reasoning, tool access) or a deterministic &lt;code&gt;SKILL&lt;/code&gt; runner (fixed procedure, no LLM calls beyond the skill's own prompts). Schedules can invoke either.&lt;/p&gt;

&lt;p&gt;The skill model makes it straightforward to build reliable automated workflows without wiring together microservices — the platform handles routing, retries, and output persistence into the Work's resource tree.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;The three moving parts — Works, MiniApps, and Schedules — are enough to build most internal tooling. Start with the unified provision endpoint to scaffold your app, use &lt;code&gt;APPEND_NODE&lt;/code&gt; schedules to run recurring tasks inside the same Work context, and use skill cards to define the agent procedures your schedules will invoke.&lt;/p&gt;

&lt;p&gt;The legacy 14-action surface is still there if you're maintaining an older Work, but new development should default to the unified API.&lt;/p&gt;

</description>
      <category>zeeren</category>
      <category>ai</category>
      <category>api</category>
      <category>webdev</category>
    </item>
    <item>
      <title>HappyCapy ships skill-share analytics, contributor leaderboards &amp; one-click install for Claude agents</title>
      <dc:creator>Lin Zhu</dc:creator>
      <pubDate>Tue, 12 May 2026 03:47:56 +0000</pubDate>
      <link>https://forem.com/lin_zhu_c66f7f4c200d3a186/happycapy-ships-skill-share-analytics-contributor-leaderboards-one-click-install-for-claude-2ig9</link>
      <guid>https://forem.com/lin_zhu_c66f7f4c200d3a186/happycapy-ships-skill-share-analytics-contributor-leaderboards-one-click-install-for-claude-2ig9</guid>
      <description>&lt;h2&gt;
  
  
  What HappyCapy is (30-second version)
&lt;/h2&gt;

&lt;p&gt;HappyCapy is a marketplace for Claude Skills — composable units of agent behavior you can drop into any Claude-powered app. Think npm for agent reasoning patterns, but with first-class Anthropic SDK integration.&lt;/p&gt;

&lt;p&gt;This week we shipped three things: skill-share analytics, a contributor leaderboard, and a one-click installer. Here's what each means for you as a builder.&lt;/p&gt;

&lt;h2&gt;
  
  
  One-click skill adoption
&lt;/h2&gt;

&lt;p&gt;Previously, adding a community skill to your agent meant copying boilerplate, wiring up the tool manifest, and hoping the author's README was accurate. The new installer does all that in one call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;happycapy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;install_skill&lt;/span&gt;

&lt;span class="n"&gt;skill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;install_skill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;web-search-summarizer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.2.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-opus-4-7&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;skill&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;# auto-wired tool definitions
&lt;/span&gt;    &lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;skill&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# author's tested system prompt
&lt;/span&gt;    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Summarize the top 3 AI papers from last week.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;skill.tools&lt;/code&gt; and &lt;code&gt;skill.system_prompt&lt;/code&gt; are pre-validated against the Anthropic tool-use spec. If the skill author updates to a new schema format, the installer adapts on the fly — your call site stays unchanged.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skill-share analytics
&lt;/h2&gt;

&lt;p&gt;As a consumer, you can now see how a skill performs in the wild before you adopt it. The dashboard surfaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Invocation counts&lt;/strong&gt; — how often the skill's tools are called across all installs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error rate by model&lt;/strong&gt; — whether the skill behaves differently on Haiku vs Sonnet vs Opus&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Latency p50 / p95&lt;/strong&gt; — useful when a skill sits in a latency-sensitive path&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token usage histogram&lt;/strong&gt; — reason about cost before you commit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As an author, the same data flows into your contributor dashboard. You can see which tools are actually invoked, where users drop off, and which model tiers trigger the most errors.&lt;/p&gt;

&lt;p&gt;Claude's tool-use behavior varies subtly across model tiers. A skill that's solid on Opus can hit edge cases on Haiku. Analytics makes that visible before it bites you in prod.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributor leaderboards
&lt;/h2&gt;

&lt;p&gt;The leaderboard ranks contributors by a composite score: installs, 30-day retention, and community ratings — not raw download counts.&lt;/p&gt;

&lt;p&gt;High-retention skills tend to be the ones that actually work in production rather than just demos that look sharp in a README. The leaderboard surfaces those.&lt;/p&gt;

&lt;p&gt;For contributors, it creates a concrete feedback loop. High installs but low retention means something is wrong with the out-of-the-box experience — more actionable than a vague thumbs-down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skills compose
&lt;/h2&gt;

&lt;p&gt;Skills are designed to layer. The installer supports loading multiple skills and merging their tool manifests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;happycapy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;install_skill&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;merge_skills&lt;/span&gt;

&lt;span class="n"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;install_skill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;web-search-summarizer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;install_skill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;persistent-memory&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;combined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;merge_skills&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-4-6&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;combined&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;combined&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[...]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;merge_skills&lt;/code&gt; handles tool name collisions and system prompt merging with a priority stack — last skill listed wins on conflicts. Inspect &lt;code&gt;combined.manifest&lt;/code&gt; to see the resolved state before you run anything.&lt;/p&gt;

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

&lt;p&gt;Skill versioning with semantic diff (see exactly what changed between v1.1 and v1.2 before upgrading) and a local test runner that replays real invocation traces against a new skill version.&lt;/p&gt;

&lt;p&gt;If you're building Claude agents and want to stop copy-pasting tool boilerplate, check it out: &lt;a href="https://happycapy.ai" rel="noopener noreferrer"&gt;https://happycapy.ai&lt;/a&gt;. Free to browse; publishing requires an account.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudeai</category>
      <category>agents</category>
      <category>devtools</category>
    </item>
  </channel>
</rss>
