Skip to content

Deploy-to-Agent-Relay button + restore intended agent resilience#3

Merged
khaliqgant merged 6 commits into
mainfrom
feat/one-click-deploy-buttons
May 27, 2026
Merged

Deploy-to-Agent-Relay button + restore intended agent resilience#3
khaliqgant merged 6 commits into
mainfrom
feat/one-click-deploy-buttons

Conversation

@khaliqgant

@khaliqgant khaliqgant commented May 27, 2026

Copy link
Copy Markdown
Member

Summary

Brings this branch up to date with main and lands two changes on top:

  • One-click deploy button (preview): adds assets/deploy-button.svg (branded "Deploy to Agent Relay" CTA matching the banner aesthetic) and a badge under the granola title linking to the cloud deploy URL. Preview-first on granola; remaining agents + top-level README pending design/URL sign-off.
  • Restore intended agent resilience: main's commit 090833b describes adding fetch resilience to hn-monitor, vendor-monitor, and spotify-releases, but that commit only actually touched granola/linear/review — the changes were never staged. This restores them:
    • hn-monitor, vendor-monitor: try/catch around fetch so a transient outage returns [] / undefined instead of crashing the run.
    • spotify-releases: fetch each artist's releases in parallel via Promise.allSettled so one failing artist doesn't sink the whole check.

Net diff vs main

 assets/deploy-button.svg  | 40 ++++++++++
 granola/README.md         |  2 ++
 hn-monitor/agent.ts       | 24 +++---
 spotify-releases/agent.ts | 14 ++--
 vendor-monitor/agent.ts   | 13 ++--

Testing

  • npx tsc --noEmit passes.

🤖 Generated with Claude Code


Summary by cubic

Adds a hosted “Launch Agent” badge to all agent READMEs with one-click deploy links. Restores resilience in hn-monitor, vendor-monitor, and spotify-releases so transient errors don’t crash runs.

  • New Features

  • Bug Fixes

    • hn-monitor: wrap front-page fetch; return [] on failure.
    • vendor-monitor: guard npm latest fetch; return undefined on failure.
    • spotify-releases: fetch per-artist releases with Promise.allSettled; skip failures.

Written for commit 5ba0e80. Summary will update on new commits. Review in cubic

khaliqgant and others added 3 commits May 26, 2026 14:35
…dge (preview)

- assets/deploy-button.svg: rounded CTA matching banner.svg aesthetic
  (brand-blue gradient echoing the logo-mark colors, white→#C9DDEE
  wordmark-gradient label, Sora-first font stack, soft halo glow). The
  glyph is the Agent Workforce logo mark lifted from banner.svg, recolored
  to light tones for contrast on the blue button. Vector, ~2.4KB, renders
  on light + dark GitHub backgrounds.
- granola/README.md: badge under the title linking to
  https://agentrelay.com/cloud/deploy?agent=granola

Preview-first: granola only. Roll to the other 5 agents + top README
pending design/URL sign-off.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
These robustness changes were described in 090833b's commit message but never
actually staged (that commit only touched granola/linear/review). Restoring
the intended behavior:
- hn-monitor, vendor-monitor: try/catch around fetch so a transient outage
  returns [] / undefined instead of crashing the run.
- spotify-releases: fetch each artist's releases in parallel via
  Promise.allSettled so one failing artist doesn't sink the whole check.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new deploy button asset, adds a deployment badge to the Granola Agent README, and enhances the resilience of several background monitor agents (Hacker News, Spotify, and npm registry) by wrapping network calls in try/catch blocks to prevent transient failures from crashing the runs. Feedback on these changes highlights potential rate-limiting issues with parallelizing Spotify API requests, and suggests logging swallowed errors in the Hacker News and npm registry monitors to aid in future troubleshooting.

Comment thread spotify-releases/agent.ts
Comment on lines +30 to +35
// Fetch every artist's releases in parallel; one failing artist shouldn't
// sink the whole check.
const perArtist = await Promise.allSettled(
artists.map((artist) => latestReleases(token, artist))
);
const releases = perArtist.flatMap((r) => (r.status === 'fulfilled' ? r.value : [])).filter((rel) => rel.date > since);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Executing up to 50 concurrent requests to the Spotify API in parallel via Promise.allSettled can easily trigger rate limits (HTTP 429) or socket exhaustion. Since this is a background cron job, running the requests sequentially with a try/catch block is safer, avoids rate limiting, and still ensures that one failing artist does not sink the entire run.

  // Fetch every artist's releases sequentially with try/catch to prevent rate limiting
  // and ensure one failing artist doesn't sink the whole check.
  const releases: Release[] = [];
  for (const artist of artists) {
    try {
      const artistReleases = await latestReleases(token, artist);
      releases.push(...artistReleases.filter((rel) => rel.date > since));
    } catch {
      // Skip failing artist
    }
  }

Comment thread hn-monitor/agent.ts
Comment on lines +46 to +56
if (!res.ok) return [];
const data = (await res.json()) as { hits: Array<{ objectID: string; title: string; url: string | null; points: number }> };
return data.hits.map((h) => ({
id: Number(h.objectID),
title: h.title,
url: h.url ?? `https://news.ycombinator.com/item?id=${h.objectID}`,
points: h.points
}));
} catch {
return [];
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Swallowing all network and parsing errors silently makes troubleshooting and debugging extremely difficult when the API is down or its response structure changes. Logging the errors to console.error provides visibility into failures without crashing the run.

Suggested change
if (!res.ok) return [];
const data = (await res.json()) as { hits: Array<{ objectID: string; title: string; url: string | null; points: number }> };
return data.hits.map((h) => ({
id: Number(h.objectID),
title: h.title,
url: h.url ?? `https://news.ycombinator.com/item?id=${h.objectID}`,
points: h.points
}));
} catch {
return [];
}
if (!res.ok) {
console.error(`HN API returned status ${res.status}`);
return [];
}
const data = (await res.json()) as { hits: Array<{ objectID: string; title: string; url: string | null; points: number }> };
return data.hits.map((h) => ({
id: Number(h.objectID),
title: h.title,
url: h.url ?? `https://news.ycombinator.com/item?id=${h.objectID}`,
points: h.points
}));
} catch (error) {
console.error('Error fetching HN front page:', error);
return [];
}

Comment thread vendor-monitor/agent.ts
Comment on lines +45 to +47
} catch {
return undefined;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Swallowing all network and parsing errors silently makes troubleshooting and debugging extremely difficult when the API is down or its response structure changes. Logging the errors to console.error provides visibility into failures without crashing the run.

  } catch (error) {
    console.error(`Error fetching latest version for ${pkg}:`, error);
    return undefined;
  }

@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR improves resilience across three monitoring agents and updates deployment documentation. HN monitor and vendor monitor now catch external service failures and return safe defaults instead of propagating errors. Spotify monitor switches to parallel per-artist fetching via Promise.allSettled, tolerating individual artist failures while collecting successful results. README adds a deployment badge.

Changes

Agent Resilience and Documentation

Layer / File(s) Summary
Deployment Documentation
granola/README.md
"Deploy to Agent Relay" badge link added to README header.
Agent Error Handling and Resilience
hn-monitor/agent.ts, spotify-releases/agent.ts, vendor-monitor/agent.ts
fetchFrontPage in HN monitor wraps network and JSON parse in try/catch, returning [] on any failure. Spotify release collector replaces sequential iteration with Promise.allSettled for concurrent per-artist fetching, flattening fulfilled results and filtering by since date while tolerating individual artist failures. latestVersion in vendor monitor catches network/parse errors and returns undefined to allow the sweep to continue.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • AgentWorkforce/agents#1: Refines the same agent implementations (hn-monitor, spotify-releases, vendor-monitor) with improved error handling and parallel fetching patterns.

Poem

🐰 Three agents now stand tall and strong,
With try-catch shields and hope lifelong,
When APIs fail and networks fall,
They brush it off and carry on, standing tall.
Parallel dreams in Spotify's dance,
A rabbit's gift: resilient, askance! 🌟

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects both main changes: the new deploy button and restoration of agent resilience across multiple files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The description clearly explains the changes: adding a deploy button badge to README and restoring fetch resilience for three agents with specific implementation details.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/one-click-deploy-buttons

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
hn-monitor/agent.ts (1)

41-56: ⚡ Quick win

Don’t swallow HN fetch failures silently.

Returning [] is good for resilience, but at Line 54 this hides operational failures as normal “no news” runs. Emit a warning before fallback.

Proposed patch
-  const stories = await fetchFrontPage();
+  const stories = await fetchFrontPage((error) =>
+    ctx.log('warn', 'hn-monitor.fetch-front-page-failed', { error: String(error) })
+  );

-async function fetchFrontPage(): Promise<Story[]> {
+async function fetchFrontPage(onError?: (error: unknown) => void): Promise<Story[]> {
   try {
     const res = await fetch('https://hn.algolia.com/api/v1/search?tags=front_page&hitsPerPage=30');
     if (!res.ok) return [];
@@
-  } catch {
+  } catch (error) {
+    onError?.(error);
     return [];
   }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@hn-monitor/agent.ts` around lines 41 - 56, The fetchFrontPage function
currently swallows failures and returns [] without any visibility; update
fetchFrontPage to log a warning when the fetch fails or when res.ok is
false—include the HTTP status and statusText for non-ok responses and include
the caught error (message/stack) in the catch handler so operational failures
are visible; reference the fetchFrontPage function, the res.ok check, and the
catch block when adding the logging call (use the project logger if available or
console.warn).
spotify-releases/agent.ts (1)

30-35: ⚡ Quick win

Log partial Spotify failures for run visibility.

At Lines 32-35, rejected artist fetches are dropped silently. Add a warning count so degraded runs are observable.

Proposed patch
   const perArtist = await Promise.allSettled(
     artists.map((artist) => latestReleases(token, artist))
   );
+  const failedArtists = perArtist.filter((r) => r.status === 'rejected').length;
+  if (failedArtists > 0) {
+    ctx.log('warn', 'spotify-releases.partial-fetch-failure', {
+      failedArtists,
+      totalArtists: artists.length
+    });
+  }
   const releases = perArtist.flatMap((r) => (r.status === 'fulfilled' ? r.value : [])).filter((rel) => rel.date > since);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@spotify-releases/agent.ts` around lines 30 - 35, The code currently drops
rejected Promise results from perArtist silently; after awaiting
Promise.allSettled(artists.map(...)) compute the number of failures by counting
entries where status === 'rejected' and emit a warning (e.g., via the module's
logger or console.warn) reporting that count and brief context so degraded runs
are visible; keep building releases as before from fulfilled results
(perArtist.flatMap(...)... filter(...)) but ensure the warning references
perArtist and latestReleases so reviewers can find where to add the log.
vendor-monitor/agent.ts (1)

38-47: ⚡ Quick win

Preserve fallback, but emit warning on registry fetch exceptions.

Line 45 currently returns undefined silently; add a warning so repeated npm/API outages are diagnosable.

Proposed patch
-    const version = await latestVersion(pkg);
+    const version = await latestVersion(ctx, pkg);

-async function latestVersion(pkg: string): Promise<string | undefined> {
+async function latestVersion(ctx: WorkforceCtx, pkg: string): Promise<string | undefined> {
   try {
     const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(pkg)}/latest`);
     if (!res.ok) return undefined;
     return ((await res.json()) as { version?: string }).version;
-  } catch {
+  } catch (error) {
+    ctx.log('warn', 'vendor-monitor.latest-version-fetch-failed', { pkg, error: String(error) });
     return undefined;
   }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vendor-monitor/agent.ts` around lines 38 - 47, The latestVersion function
currently swallows network/JSON errors; keep returning undefined on failure but
log a warning with the package name and the error so outages are diagnosable. In
the latestVersion function's catch block, change it to catch the thrown error
(e.g. catch (err)) and call a warning logger (console.warn or an existing
logger) with a descriptive message including pkg and err, then return undefined;
leave the existing res.ok early-return behavior unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@hn-monitor/agent.ts`:
- Around line 41-56: The fetchFrontPage function currently swallows failures and
returns [] without any visibility; update fetchFrontPage to log a warning when
the fetch fails or when res.ok is false—include the HTTP status and statusText
for non-ok responses and include the caught error (message/stack) in the catch
handler so operational failures are visible; reference the fetchFrontPage
function, the res.ok check, and the catch block when adding the logging call
(use the project logger if available or console.warn).

In `@spotify-releases/agent.ts`:
- Around line 30-35: The code currently drops rejected Promise results from
perArtist silently; after awaiting Promise.allSettled(artists.map(...)) compute
the number of failures by counting entries where status === 'rejected' and emit
a warning (e.g., via the module's logger or console.warn) reporting that count
and brief context so degraded runs are visible; keep building releases as before
from fulfilled results (perArtist.flatMap(...)... filter(...)) but ensure the
warning references perArtist and latestReleases so reviewers can find where to
add the log.

In `@vendor-monitor/agent.ts`:
- Around line 38-47: The latestVersion function currently swallows network/JSON
errors; keep returning undefined on failure but log a warning with the package
name and the error so outages are diagnosable. In the latestVersion function's
catch block, change it to catch the thrown error (e.g. catch (err)) and call a
warning logger (console.warn or an existing logger) with a descriptive message
including pkg and err, then return undefined; leave the existing res.ok
early-return behavior unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a52bf931-6d2b-463e-b753-95a651a2f2ab

📥 Commits

Reviewing files that changed from the base of the PR and between 416631a and 5189a67.

⛔ Files ignored due to path filters (1)
  • assets/deploy-button.svg is excluded by !**/*.svg
📒 Files selected for processing (4)
  • granola/README.md
  • hn-monitor/agent.ts
  • spotify-releases/agent.ts
  • vendor-monitor/agent.ts

khaliqgant and others added 3 commits May 27, 2026 14:31
Replace assets/deploy-button.svg with the canonical "Launch Agent" badge
from https://agentrelay.com/launch-agent.svg (renamed to launch-agent.svg)
and update the granola badge label/path to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reference https://agentrelay.com/launch-agent.svg directly so the badge
tracks the canonical hosted asset; drop the local copy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
All six agents now carry the hosted Launch Agent badge linking to their
respective cloud deploy URL (?agent=<name>), matching granola.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@khaliqgant khaliqgant merged commit 353afb9 into main May 27, 2026
2 checks passed
@khaliqgant khaliqgant deleted the feat/one-click-deploy-buttons branch May 27, 2026 12:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant