Juicebox Sdk PatternsSAFE
Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com.
Overview
Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com.
4f83675ca38aOBSERVED · 2026-10-09Host compatibility
What the documentation claims. We have not run a compatibility test.
| Host | Status | Notes |
|---|---|---|
| claude-code | mentioned | |
| cursor | mentioned |
What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
--- name: juicebox-sdk-patterns description: 'Apply production Juicebox SDK patterns. Trigger: "juicebox patterns", "juicebox best practices". ' allowed-tools: Read, Write, Edit version: 1.16.0 license: MIT author: Jeremy Longshore <[email protected]> tags: - saas - recruiting - juicebox compatibility: Designed for Claude Code --- # Juicebox SDK Patterns ## Overview Production-ready patterns for the Juicebox AI-powered people search API. Juicebox provides REST endpoints for searching professional profiles and enriching candidate data. The API authenticates via `JUICEBOX_API_KEY` and returns structured profile objects with LinkedIn URLs as natural dedup keys. A singleton client centralizes rate-limit handling across search and enrich endpoints. ## Singleton Client ```typescript const JUICEBOX_BASE = 'https://api.juicebox.work/v1'; let _client: JuiceboxClient | null = null; export function getClient(): JuiceboxClient { if (!_client) { const apiKey = process.env.JUICEBOX_API_KEY; if (!apiKey) throw new Error('JUICEBOX_API_KEY must be set — get it from juicebox.work/settings'); _client = new JuiceboxClient(apiKey); } return _client; } class JuiceboxClient { private headers: Record<string, string>; constructor(apiKey: string) { this.headers = { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }; } async search(query: string, limit = 20): Promise<SearchResponse> { const res = await fetch(`${JUICEBOX_BASE}/search`, { method: 'POST', headers: this.headers, body: JSON.stringify({ query, limit }) }); if (!res.ok) throw new JuiceboxError(res.status, await res.text()); return res.json(); } async enrich(linkedinUrl: string): Promise<Profile> { const res = await fetch(`${JUICEBOX_BASE}/enrich`, { method: 'POST', headers: this.headers, body: JSON.stringify({ linkedin_url: linkedinUrl }) }); if (!res.ok) throw new JuiceboxError(res.status, await res.text()); return res.json(); } } ``` ## Error Wrapper ```typescript export class JuiceboxError extends Error { constructor(public status: number, message: string) { super(message); this.name = 'JuiceboxError'; } } export async function safeCall<T>(operation: string, fn: () => Promise<T>): Promise<T> { try { return await fn(); } catch (err: any) { if (err instanceof JuiceboxError && err.status === 429) { await new Promise(r => setTimeout(r, 5000)); return fn(); } if (err instanceof JuiceboxError && err.status === 401) throw new JuiceboxError(401, 'Invalid JUICEBOX_API_KEY'); throw new JuiceboxError(err.status ?? 0, `${operation} failed: ${err.message}`); } } ``` ## Request Builder ```typescript class JuiceboxSearchBuilder { private body: Record<string, any> = {}; query(q: string) { this.body.query = q; return this; } limit(n: number) { this.body.limit = Math.min(n, 100); return this; } location(loc: string) { this.body.location = loc; return this; } title(t: string) { this.body.title_filter = t; return this; } company(c: string) { this.body.company_filter = c; return this; } yearsExp(min: number, max: number) { this.body.years_experience = { min, max }; return this; } build() { return this.body; } } // Usage: new JuiceboxSearchBuilder().query('ML engineer').location('San Francisco').yearsExp(3, 8).build(); ``` ## Response Types ```typescript interface Profile { id: string; name: string; title: string; company: string; linkedin_url: string; location: string; skills: string[]; experience_years: number; } interface SearchResponse { profiles: Profile[]; total: number; has_more: boolean; cursor?: string; } interface EnrichResult { profile: Profile; education: Array<{ school: string; degree: string; year: number }>; experience: Array<{ company: string; title: string; start: string; end: string | null }>; } ``` ## Testing Utilities ```typescript export function mockProfile(overrides: Partial<Profile> = {}): Profile { return { id: 'prof-001', name: 'Jane Smith', title: 'Senior ML Engineer', company: 'Acme Corp', linkedin_url: 'https://linkedin.com/in/janesmith', location: 'San Francisco, CA', skills: ['Python', 'PyTorch', 'MLOps'], experience_years: 6, ...overrides }; } export function mockSearchResponse(count = 3): SearchResponse { return { profiles: Array.from({ length: count }, (_, i) => mockProfile({ id: `prof-${i}` })), total: count, has_more: false }; } ``` ## Error Handling | Pattern | When to Use | Example | |---------|-------------|---------| | `safeCall` wrapper | All Juicebox API calls | Structured error with operation context | | Retry on 429 | Batch search pipelines | 5s backoff before retry | | LinkedIn dedup | Multi-query search | `Set<string>` on `linkedin_url` prevents duplicates | | Cursor pagination | Search results > 100 | Pass `cursor` from previous response | ## Prerequisites - A typed client boundary, secret-manager reference, sandbox workspace, approved source/destination allowlist, and synthetic prospect fixture. ## Instructions 1. Construct clients from scoped environment configuration and reject unknown workspace, source, or destination before a request is sent. 2. Centralize source-authority, suppression, schema, redaction, and idempotency checks in the client boundary. 3. Model partial/denied responses explicitly; never turn a denied or unverified enrichment into a success or export fallback. 4. Test malformed data, rate limits, source/suppression rejection, and rollback using synthetic fixtures only. ## Output Produce a client-contract receipt with SDK revision, environment, source/destination policy revisions, fixture result, error classification, aggregate counts, export-count assertion, and rollback behavior. Exclude contacts, enrichment data, and credentials. ## Examples `sdk=v3; env=sandbox; source=synthetic; destination=approved; suppression=pass; malformed=blocked; contacts_exported=0; telemetry=aggregate-only` is a safe SDK result. ## Resources - Ju
Trust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | PASS |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (0)
No findings outside the package's declared scope.
Gates applied: no_behavioural_pass.
4f83675ca38afull audit observations/trust-audit/skill/jeremylongshore__juicebox-sdk-patterns.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-09 | 4f83675ca38a | SAFE | B | 89 | first audit |
Questions
What does the Juicebox Sdk Patterns skill do?
Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com.
Is Juicebox Sdk Patterns safe to install?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.
What can Juicebox Sdk Patterns access on my machine?
The audit observed no filesystem, network or shell use at all in its source.
Which assistants does Juicebox Sdk Patterns work with?
Its documentation mentions claude-code and cursor. That is what the text claims, not a compatibility test we ran.
How current is this page?
The grade is for one exact copy of the source (4f83675ca38a), read on 2026-10-09. The repository is watched, and a new audit runs when it changes — this is the first audit.