Install
$ agentstack add skill-leonardhope-claude-skill-for-patent-examiner-intelligence-claude-skill-for-patent-examiner-intelligence ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Patent Examiner Intelligence
> Status: V1 thin slice — only the data-layer skeleton, a coarse > status-bucket breakdown, and a minimal dashboard are wired up. Deep > insights (rejection fingerprint, citation kryptonite, tells, disposition > histogram, Action Kits, twin cases) are design-complete in > [DESIGN.md](./DESIGN.md) but not yet built. Do not promise the user > analysis that isn't in the current profile dict.
What this skill does
Generates a decision-grade profile of a USPTO patent examiner, tailored to the attorney's specific application when claims are available. The scaffold produces two output artifacts from the same Python data layer:
- A Markdown chat headline — fast-check summary with the key numbers
and the dashboard's file path
- A standalone interactive HTML dashboard — self-contained single
file, opens in any browser, works offline forever, can be emailed or archived with the matter record
The dashboard is the primary deliverable for serious drafting work. The chat headline is the fast check.
When to fire this skill
Fire when the user says anything along the lines of:
- "Profile examiner [name]" / "Analyze examiner [name]"
- "Tell me about examiner [name]" / "Who is examiner [name]"
- "What should I know about my examiner on [app number]"
- "Prep me for an interview with [name]"
- "Should I appeal / RCE / continue with [name]"
- "New OA from [name], help me draft a response"
- "Just got assigned to [name], what can I expect"
Also fire when the user pastes an office action or mentions an assigned examiner as part of a prosecution-planning question — even implicitly.
Context resolution — three paths
Follow DESIGN.md's dual-path context resolution:
Path A — Application number provided and publicly accessible. Call resolve_from_app(app_number) to pull the examiner, art unit, title, status, filing date, and CPC automatically from the file wrapper. Proceed to profile generation with no follow-up questions.
Path B — Application number provided but not accessible (404, pre-publication, nonpublication request). resolve_from_app() returns None. Say to the user in plain English:
> That application doesn't appear to be publicly accessible — that's > normal for pre-publication or nonpub-request cases. Who's the examiner > and what's the art unit?
Then proceed with the user's answer to the profile generation step.
Path C — Direct invocation, no application number. User says "profile examiner Chen, Sarah in AU 2144". Skip the resolution step entirely and go straight to profile generation.
If the user doesn't specify years, default to 5.
How to run the skill
After resolving the context, run the data-layer orchestrator and the renderer. Use the project's virtual environment (.venv/bin/python) if the user has already run get_started.py; otherwise tell them to run python3 get_started.py first.
import sys
sys.path.insert(0, ".") # project root
from scripts.context_resolver import resolve_from_app # Path A only
from scripts.examiner_profile import profile_examiner
from scripts.dashboard_renderer import render_dashboard
# Path A: resolve from app number (if the user gave one)
ctx = resolve_from_app("17123456") # returns None if inaccessible
examiner = ctx["examiner"] # e.g. "RICKS, DONNA J"
art_unit = ctx["art_unit"] # e.g. "2618"
# Build the profile (data layer, no LLM calls from Python)
# max_101_examples controls how many §101-overcoming amendments are
# retrieved and embedded in the dashboard (default 10). Higher = more
# examples but slower build and larger file. Ask the user if they
# want more ("how many §101 examples would you like? default is 10").
profile = profile_examiner(
examiner=examiner,
art_unit=art_unit,
years=5,
max_101_examples=10, # default; set to 0 for unlimited
)
# Render the dashboard (writes to output/.html)
# After generating the profile, if synthesis_101 data is available,
# read the claim texts and generate the §101 synthesis narrative.
# Then pass it to render_dashboard so it's embedded in the HTML.
narrative = {}
if profile.get("synthesis_101") and profile["synthesis_101"].get("cases"):
# Claude: read the claim_1_text from each case in
# profile["synthesis_101"]["cases"] and write a synthesis
# paragraph following the PROMPT below. Store it in:
narrative["synthesis_101"] = "..." # Claude fills this in
dashboard_path = render_dashboard(profile, narrative=narrative)
A fresh profile takes ~3–10 seconds for a typical examiner (1 API call per 100 apps, paginated, capped at 1000 apps by default). Subsequent profiles for the same examiner are cached for 30 days and return in milliseconds.
Output — what to show the user
Render the Markdown chat headline yourself, in your response to the user. Use the profile_dict's numeric fields verbatim, and always pair a prescriptive call with its supporting number (the "prescriptive with descriptive receipts" voice from DESIGN.md). Example shape:
> [examiner], AU [unit] > [N] applications in the last [years] years — [breakdown] > > [One-sentence top-level recommendation, if the data supports one] > > Dashboard: file:///.../output/[cache_key].html — open this for the > full drill-down and the reasoning trace behind every metric.
Then print the file path so the user can click or open it in a browser.
V1 thin slice — what's in the profile dict
profile = {
"examiner": str,
"art_unit": str,
"years": int,
"generated_at": str (ISO-8601 UTC),
"cache_key": str,
"date_range": {"from": str, "to": str},
"apps": [ # list of dicts, one per app
{
"application_number": str,
"title": str,
"status": str,
"status_bucket": "allowed" | "pending" | "abandoned" | "other",
"filing_date": str,
"grant_date": str,
"patent_number": str,
"examiner": str,
"art_unit": str,
"cpc": list of str,
},
...
],
"metrics": {
"sample_size": {value, source_apps, source_calls, threshold, what_would_change_it},
"total_in_api": {value, ...},
"status_breakdown": {value: dict[bucket, count], ...},
},
"_meta": {
"api_calls": list of call records,
"total_api_calls": int,
"total_duration_seconds": float,
"from_cache": bool,
},
}
Every metric is wrapped in a reasoning-trace provenance struct: {value, source_apps, source_calls, threshold, what_would_change_it}. This is what the dashboard's "Why" buttons surface. Do not strip provenance when summarizing — it's the trust unlock.
Analysis split — what Python does vs. what Claude does
Per DESIGN.md's "Analysis split" decision, all LLM work is done by Claude in conversation, not by Python. Python returns raw material; Claude does the qualitative reasoning.
- Python (data layer): fetches apps, computes deterministic stats,
captures provenance. No LLM calls.
- Claude in conversation (this file's instructions): reads the raw
material from the profile dict and performs tells extraction, twin-case narrative generation, winning-play classification, Action Kit recommendations, and Short Version synthesis.
- Python (rendering layer): takes the profile dict + Claude's
generated narrative content and produces the Markdown chat headline and the HTML dashboard.
What's built vs. what's still coming
Built and operational (produce data in the profile dict):
- §1 Rejection Fingerprint — rejection type distribution, multi-basis
stacking rate, first-action basis distribution, trend by year
- §2 Citation Fingerprint — top-cited refs, kryptonite, paper tigers
- §4 Disposition Stats — allowance/abandonment rates, first-action
allowance, actions-to-allowance histogram
- §5 Appeal Posture — PTAB decisions joined by app number
- §7 Confidence & Data Quality — red flags, overall confidence level
- Winning Patterns — what worked to get allowed (prosecution sequence)
- Markdown chat headline (
format_profile.py) - Standalone HTML dashboard with charts, drill-down, download buttons
Not yet built (Claude should not promise these):
- §3 Tells — phrases preceding allowance vs. final rejection (see
prompt template below for how Claude extracts these in conversation)
- §6 Twin-case matching — structurally-closest cases to the user's
claims (needs claim text as input)
- Action Kits — Interview / Response / Strategic / Expectations
tactical playbooks (see prompt templates below)
Prompt templates for Claude-in-conversation tasks
These prompts guide Claude through the qualitative analysis that Python doesn't do. Claude reads the profile dict's raw material and produces the synthesis. The data layer provides the facts; Claude provides the judgment.
PROMPT: Short Version (use when rendering the chat headline)
Read the profile dict and produce a three-paragraph prescriptive summary following this structure:
Paragraph 1 — Who they are: State the examiner's name, art unit, sample size, effective date range, and overall confidence level. Give the headline number (allowance rate) with context ("below/above average" if you have an AU comparison). State the dominant rejection basis.
Paragraph 2 — What works / what doesn't: Pull from winning_patterns.primary_pattern_distribution. State the primary winning move, the interview rate in allowed cases, and whether claim changes were required. Use the format: "What works: [pattern] ([N] of [M] allowed). What doesn't: [anti-pattern]." Use real numbers, not vague language.
Paragraph 3 — What to do next: Based on the user's current situation (response drafting? interview prep? strategic decision?), give a specific one-sentence recommendation with the supporting number. E.g., "Schedule an interview — her post-interview allowance rate is 67% vs. 43% paper-only."
PROMPT: Tells extraction (§3)
When the user asks about an examiner's language patterns or "tells," look at the rejection_fingerprint.rejections_by_basis data and the profile's OA text (if the user pastes an OA or references one). Then:
- Identify phrases the examiner uses repeatedly across OAs that
signal the rejection is softening vs. hardening
- Note any distinctive framing — e.g., does the examiner use
"significantly more" language for §101, or "motivated to combine" vs. "would have been obvious" for §103?
- Flag any language that historically preceded an allowance in this
examiner's docket
This is qualitative work that requires Claude's judgment. The data layer provides the rejection records and their basis codes; Claude reads the actual OA text and does the linguistic analysis.
PROMPT: §101 Amendment Synthesis (the big value-add)
When the user has a §101 rejection from this examiner and the profile has synthesis_101.cases with extracted claim 1 text, Claude should:
- Read all the claim 1 texts from the synthesis_101 section.
These are the independent claims that overcame this examiner's §101.
- Identify the structural pattern. What do these claims have in
common that satisfied the examiner's §101 analysis? Common patterns to look for:
- Specific hardware or system architecture elements
- Particular data transformations or processing steps
- Unconventional technical implementations (not just "on a computer")
- Limitations that tie the abstract concept to a specific technology
- "Wherein" clauses that add technical specificity
- Read the user's pending claim 1 from the conversation context
(the user will paste it or point to a saved file).
- Generate a specific amendment suggestion. Not "add more technical
detail" (useless). Instead: "Based on the N cases where applicants overcame this examiner's §101, the pattern is [X]. Your claim 1 currently lacks [Y]. Consider adding a limitation along the lines of [specific language] to claim 1, which mirrors the approach in [app number] that was allowed after the same §101 framework."
- Cite the source. Every suggestion must reference the specific
allowed case it's based on, with a Patent Center link.
Critical: This is a SUGGESTION, not legal advice. Frame it as "based on the pattern in this examiner's allowed cases, consider..." — not "you should amend to..." The attorney makes the final call.
PROMPT: Action Kit — Interview
When the user is preparing for an examiner interview, produce the Interview Kit using data from the profile dict:
- Lead with: The rejection basis where the examiner is weakest
(check appeal_posture — any reversals? On which grounds?)
- Likely concessions: From
winning_patterns, what has worked
in similar cases? If interviews appear in the winning patterns, what did the applicant propose?
- Don't raise: From
rejection_fingerprint, which basis has the
highest final-rejection rate? If §112 leads to finals more than §103, save §112 for the written response.
- Her interview style: From
winning_patterns.interview_rate_in_allowed
— is this examiner high-value for interviews or not?
PROMPT: Action Kit — Response
When the user is drafting a response to an OA from this examiner:
- Opening amendment: From
winning_patterns, what's the primary
winning move? If "amendment" is dominant, recommend amending.
- Fallback: If "after-final amendment" appears in patterns, note
that this examiner accepts after-final responses.
- Arguments to deploy: From the rejection basis distribution,
which basis is weakest in the docket (lowest count)?
- Arguments to skip: If
winning_patterns.claims_change_rateis
high (>70%), argument-only doesn't work — don't waste the attorney's time on argument-only responses.
PROMPT: Action Kit — Strategic
When the user is deciding between appeal, RCE, or continuation:
- Appeal odds: From
appeal_posture— reversal rate + grounds.
If rate > 40% on the relevant basis, appeal may be worth it.
- RCE behavior: From
winning_patterns, does RCE appear? If
"RCE + amendment" is a winning pattern, RCE is productive.
- Continuation: From
disposition_stats, are there continuation
cases in the docket? How do they fare?
PROMPT: Action Kit — Expectations
When the user has a newly-assigned examiner (no OA yet):
- Likely first action: From
rejection_fingerprint.first_action_basis_distribution,
what basis does the examiner lead with?
- Brace for: From the multi-basis stacking rate — if 100%, expect
stacked rejections.
- Whether to pre-plan an interview: From
winning_patterns.interview_rate_in_allowed
— if > 30%, worth scheduling proactively.
Error handling
- API key missing: the vendored USPTO client raises
APIError("[SETUP_REQUIRED] ..."). Tell the user to run python3 get_started.py to configure the key.
- Application not accessible (Path B trigger):
resolve_from_app()
returns None. Ask the user for the examiner and art unit directly.
- Examiner name format mismatch: USPTO's
examinerNameTextfield is
typically "Last, First M". If the user gives you a different format, try to match it or ask for clarification.
- Very small sample size (< 10 apps): say so explicitly in the chat
headline — tiny samples produce unreliable predictions.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: LeonardHope
- Source: LeonardHope/Claude-Skill-for-Patent-Examiner-Intelligence
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.