| name | patent-examiner-intelligence |
| description | Build deep, evidence-grounded profiles of USPTO patent examiners from their public examination history. Use when the user asks to profile an examiner, analyze an examiner, prepare for an examiner interview, draft a response against a specific examiner, decide on appeal-vs-RCE-vs-continuation with a specific examiner, or understand an examiner who has just been assigned. Produces a Markdown chat headline plus a standalone interactive HTML dashboard written to disk. |
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 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, ".")
from scripts.context_resolver import resolve_from_app
from scripts.examiner_profile import profile_examiner
from scripts.dashboard_renderer import render_dashboard
ctx = resolve_from_app("17123456")
examiner = ctx["examiner"]
art_unit = ctx["art_unit"]
profile = profile_examiner(
examiner=examiner,
art_unit=art_unit,
years=5,
max_101_examples=10,
)
narrative = {}
if profile.get("synthesis_101") and profile["synthesis_101"].get("cases"):
narrative["synthesis_101"] = "..."
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_rate is
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
examinerNameText field 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.