Skip to content

feat(skills): bundle build-monetized-app skill#7160

Merged
lalalune merged 2 commits into
elizaOS:developfrom
RemilioNubilio:bot/skill-build-monetized-app
Apr 29, 2026
Merged

feat(skills): bundle build-monetized-app skill#7160
lalalune merged 2 commits into
elizaOS:developfrom
RemilioNubilio:bot/skill-build-monetized-app

Conversation

@RemilioNubilio
Copy link
Copy Markdown
Contributor

@RemilioNubilio RemilioNubilio commented Apr 28, 2026

Summary

Add a new bundled skill — build-monetized-app — that teaches the agent how to build a monetized app on Eliza Cloud, deploy it as a container, and route the earnings back into hosting via the existing pay-as-you-go-from-earnings cron.

The skill exists because monetized apps are how a Milady-style autonomous agent stays online: container hosting bills daily, the container-billing cron pulls from redeemable_earnings_ledger before credit_transactions, so any app that earns more than its hosting cost keeps the agent alive without owner intervention. This is a real product constraint that the agent should be aware of when picking what to build.

What's in here

packages/skills/skills/build-monetized-app/
  SKILL.md                              # ~4KB: purpose, when-to-use, default
                                        # flow, links to references
  references/
    sdk-flow.md                         # ~4KB: the 6-step @elizaos/cloud-sdk
                                        # deploy + monetize flow with full code
    survival-economics.md               # ~4KB: earnings/hosting loop math,
                                        # why earnings come before credits
    failure-modes.md                    # ~5KB: recovery table for real
                                        # failures (name collision, deploy
                                        # health-check, image push, etc.)

Layout follows the existing convention used by eliza-cloud and eliza-app-development:

  • Top-level SKILL.md is small and contains: frontmatter (name + description), purpose, default flow, links to references, and explicit out-of-scope list
  • References are deep-dive pages, kept ~100 lines each, loaded by the agent only when the skill is being actively applied

Why a separate skill rather than extending eliza-cloud

eliza-cloud is the broad "Cloud is your backend" skill — auth, APIs, redirects. build-monetized-app is the narrow "you are building an app to monetize and stay alive" skill. Different audience (agent-the-builder vs agent-the-consumer), different decisions (markup %, container tier, retry strategy on deploy failure), different mental model (survival-economics).

The two are cross-referenced: build-monetized-app/SKILL.md defers to eliza-cloud for auth-flow details. No duplicated content.

Verification — live on running bot

Synced into a milady deployment. Before the new skill:

[AgentSkills] Initialized with 31 skills (workspace: 1, managed: 1, bundled: 29, plugin: 0, extra: 0)

After:

[AgentSkills] Initialized with 32 skills (workspace: 1, managed: 1, bundled: 30, plugin: 0, extra: 0)

ensure-skills.mjs's existing ensureShippedSkills() walks the directory, seeded the new skill into ~/.eliza/skills/build-monetized-app/ on first run, and the AgentSkills service registered it at boot. No loader changes needed — the discovery path is already directory-driven.

The frontmatter name matches the directory name and the description is structured so the eligibility selector picks the skill for build/deploy/monetize tasks without overlapping with eliza-cloud.

What's intentionally NOT in here

  • A wrapper API around @elizaos/cloud-sdk. The skill teaches the agent to call the SDK directly. Wrappers add no value and rot when the SDK evolves.
  • Auto-creation of an affiliate code per app. Affiliate codes belong to the owner across all their apps. The skill inherits whatever the owner configured.
  • An always-on assumption. The skill works whether the org has pay_as_you_go_from_earnings true (default) or false. The earnings flow is described; the toggle is the owner's call.
  • A retry loop for the entire flow. Each step is idempotent; the failure-modes reference describes per-step recovery.

5-rule check

  1. No meaningless wrappers — markdown only; the skill points the agent at @elizaos/cloud-sdk directly.
  2. Reuse existing functions — uses the existing ensureShippedSkills() discovery (no new loader), references the existing eliza-cloud skill instead of re-explaining cloud auth.
  3. No unused/inline-able type variables — n/a, content-only change.
  4. No non-essential parameters — n/a.
  5. Clean separation — one skill per concern; SKILL.md is the entry point; references are loaded only when the skill is actively applied.

🤖 Generated with Claude Code

Greptile Summary

This PR adds a new bundled build-monetized-app skill — four markdown files teaching the agent to register an Eliza Cloud app, build and push a container, configure markup, and hook into the earnings-funded hosting loop.

  • P1 (sdk-flow.md step 3–5): The polling loop that waits for load_balancer_url to become available never captures its result into a variable; step 5 then reads container.load_balancer_url from the initial creation response, which is null, causing the patchApiV1AppsById call to set app_url: null and breaking the OAuth redirect and CORS configuration for every deployment.

Confidence Score: 4/5

Safe to merge after fixing the missing polling-result variable in sdk-flow.md step 3; the P1 causes every agent-driven deploy to silently set a null app_url.

One P1 finding (stale container variable in the step 3→5 transition) sets the ceiling at 4. The remaining findings are P2 style/robustness suggestions that do not block merging.

packages/skills/skills/build-monetized-app/references/sdk-flow.md — the polling-result assignment gap between step 3 and step 5.

Important Files Changed

Filename Overview
packages/skills/skills/build-monetized-app/SKILL.md New skill entry point with frontmatter, purpose, default flow sketch, and auth/monetization header guidance; references private cron path that agents cannot resolve, but otherwise structurally correct.
packages/skills/skills/build-monetized-app/references/sdk-flow.md 6-step deploy+monetize flow; the polled container result is never stored, so step 5 will use a null load_balancer_url from the initial creation response — breaking app_url/CORS patching.
packages/skills/skills/build-monetized-app/references/survival-economics.md Accurate survival-economics narrative; references private cron path (already flagged in prior thread) but content is otherwise self-contained and correct.
packages/skills/skills/build-monetized-app/references/failure-modes.md Well-structured recovery table covering registration, image push, deploy, markup, and auth failures; no logical issues found.

Sequence Diagram

sequenceDiagram
    participant Agent
    participant CloudSDK as cloud-sdk
    participant Registry as Container Registry

    Agent->>CloudSDK: postApiV1Apps(name, placeholder_url)
    CloudSDK-->>Agent: app.id, apiKey

    Agent->>Registry: docker build + push image
    Registry-->>Agent: image tag ready

    Agent->>CloudSDK: postApiV1Containers(image, appId, cpu, memory)
    CloudSDK-->>Agent: container(id, status=pending, load_balancer_url=null)

    loop Poll until running
        Agent->>CloudSDK: getApiV1ContainersById(id)
        CloudSDK-->>Agent: container(status, load_balancer_url)
    end

    Note over Agent: polled result not stored - container.load_balancer_url remains null

    Agent->>CloudSDK: patchApiV1AppsById(inference_markup_percentage=20)
    CloudSDK-->>Agent: markup set

    Agent->>CloudSDK: patchApiV1AppsById(app_url=null, allowed_origins=[null])
    CloudSDK-->>Agent: 400 invalid_origin
Loading

Reviews (2): Last reviewed commit: "fix(skill/build-monetized-app): point at..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Add a new bundled skill, `build-monetized-app`, that gives the agent
the recipe for building an app on Eliza Cloud that earns markup-share
revenue, deploying it as a container, and routing its earnings back
into hosting via the existing pay-as-you-go-from-earnings cron.

The skill exists because monetized apps are how a Milady-style
autonomous agent stays online: container hosting bills daily, the
container-billing cron pulls from `redeemable_earnings_ledger` before
`credit_transactions`, so any app that earns more than its hosting
cost keeps the agent alive without owner intervention. This is a
real product constraint, not theoretical — the survival-economics
reference walks through the exact accounting (cron at
`app/api/cron/container-billing/route.ts`).

Layout follows the existing convention used by `eliza-cloud` and
`eliza-app-development`:

  packages/skills/skills/build-monetized-app/
    SKILL.md                              # 4 KB — purpose, when-to-use,
                                          # default flow, links to references
    references/
      sdk-flow.md                         # 4 KB — the 6-step
                                          # @elizaos/cloud-sdk deploy + monetize flow
      survival-economics.md               # 4 KB — earnings/hosting loop, why this matters
      failure-modes.md                    # 5 KB — recovery table for real failures

The frontmatter `name` matches the directory name (`build-monetized-app`)
and the `description` is written so the skill-eligibility selector
picks it up for build/deploy/monetize tasks without overlapping with
the broader `eliza-cloud` skill (which covers cloud as a backend in
general). The two skills are explicitly cross-referenced.

Verified live:

  bot before: AgentSkills: Initialized with 31 skills (..., bundled: 29, ...)
  bot after:  AgentSkills: Initialized with 32 skills (..., bundled: 30, ...)

ensure-skills.mjs's `ensureShippedSkills()` discovered the new
directory and seeded it into `~/.eliza/skills/` on next run; the
AgentSkills service then registered it at boot. No loader changes
needed because the discovery path is already directory-driven.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 28, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b28f4e1b-faf6-4248-a405-69bd3e9869cb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the Docs label Apr 28, 2026
Comment on lines +60 to +69
memory: 512,
env: { /* image-specific runtime vars */ },
},
});
```

After `postApiV1Containers` returns, poll `getApiV1ContainersById(container.id)` until `status === "running"` and `load_balancer_url` is populated. Health-check failures here mean the image's server doesn't bind to `$PORT` correctly — pull `cloud.routes.getApiV1ContainersByIdLogs(container.id)` and surface to the human.

## 4. Set markup

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 image vs ecr_image_uri field name conflict

The existing eliza-cloud/references/apps-and-containers.md describes the container deployment flow as: (1) get temporary ECR credentials, (2) push a Docker image, (3) create a container with ecr_image_uri. This skill's postApiV1Containers payload uses image instead. An agent choosing between these two skills will get different field names for the same call, and one of them will silently fail or be ignored by the API. If ecr_image_uri is the schema field, passing image will leave the image unset and the deployment will never start.

Comment on lines +45 to +47

- Listen on `$PORT` (cloud sets this at runtime)
- Expose a health-check endpoint
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Broken reference path for edad-chat

cloud-mini-apps/edad-chat/server.ts does not exist in this repository. An agent instructed to "copy its requestForwarder" will not be able to find the file. Either include the relevant snippet inline (or in a dedicated references/ file), or point to the correct path / external URL so the reference is actually followable.


Container hosting is pay-as-you-go, billed daily. The cron at `app/api/cron/container-billing/route.ts` runs once per day and, for each container:

1. Computes the day's hosting cost (CPU + RAM at the tier's per-second rate)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Cron path not resolvable from this repo

app/api/cron/container-billing/route.ts doesn't exist under this repo's tree (it lives in the private eliza/cloud sub-repo). The agent will fail to look it up if instructed to inspect the billing logic. The survival-economics.md doc would be more useful if it described the billing rules inline rather than directing the agent to a path it can't open.

Address feedback: the original SKILL.md mentioned a "shipped reference
implementation" without a clickable link, which was thin. The canonical
public reference lives at:

  https://github.com/elizaOS/cloud-mini-apps/tree/main/apps/edad-chat

(public repo, latest commit 2026-04-27 refactored it to use
@elizaos/cloud-sdk). Restore that as the primary external reference in
SKILL.md, and explicitly point at it from references/sdk-flow.md as
the canonical shape for the chat-forwarder.

Skill remains self-contained — the inline minimal example in
references/sdk-flow.md still works for agents that don't want to
clone an external repo. The cloud-mini-apps reference is for agents
that want full code.
Comment on lines +97 to +112

```ts
const container = await cloud.routes.postApiV1Containers({
json: {
image: `<registry>/<repo>:<tag>`,
appId,
cpu: 256,
memory: 512,
env: { /* image-specific runtime vars */ },
},
});
```

After `postApiV1Containers` returns, poll `getApiV1ContainersById(container.id)` until `status === "running"` and `load_balancer_url` is populated. Health-check failures here mean the image's server doesn't bind to `$PORT` correctly — pull `cloud.routes.getApiV1ContainersByIdLogs(container.id)` and surface to the human.

## 4. Set markup
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Polled container result never captured — container.load_balancer_url will be null in step 5

Step 3 creates the container into const container = ... and then instructs the agent to poll getApiV1ContainersById(container.id) until load_balancer_url is populated — but the polling result is never assigned to a variable. Step 5 then references container.load_balancer_url, which is still the value from the initial creation response, where load_balancer_url is null or undefined. An agent that follows this code literally will call patchApiV1AppsById with app_url: null and allowed_origins: [null], producing a 400 invalid_origin / 400 invalid_app_url error and leaving the OAuth redirect broken.

The fix is to assign the polled result, for example:

let running = container;
while (running.status !== "running" || !running.load_balancer_url) {
  await new Promise(r => setTimeout(r, 5000));
  running = await cloud.routes.getApiV1ContainersById(container.id);
}

Then step 5 should use running.load_balancer_url instead of container.load_balancer_url.

@lalalune lalalune merged commit 273f4c7 into elizaOS:develop Apr 29, 2026
3 of 4 checks passed
lalalune added a commit that referenced this pull request May 3, 2026
…d-app

feat(skills): bundle build-monetized-app skill
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants