elicit

elicit is a skill for Claude Code from jongwony/epistemic-protocols. It costs 44 tokens per session (3,942 once invoked), scanned A, original, MIT.

A guided conversation method for turning a vague or unresolved decision into a specific endpoint. It examines the user's code, rules, past sessions, or environment, then asks questions based on the decision factors it finds.

In plain words
What is it for?
Use it to clarify ambiguous intent and choose a concrete direction for a task.
Why use it?
It helps when the user knows there is a decision to make but cannot yet state the relevant criteria. Unresolved factors can be brought back into later question cycles.

Skill for Claude Code

Written for Claude Code: shipped in a Claude Code plugin.

Part of the euporia plugin — 1 skill shipped together

Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

agentmods
npx agentmods add skills/jongwony/epistemic-protocols/elicit
Any agent
npx skills add jongwony/epistemic-protocols --skill elicit
Clone the repo
git clone --depth 1 https://github.com/jongwony/epistemic-protocols

Made for: Claude Code.

Or install euporia, the plugin that ships this one along with the rest of its 1 skill.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for elicit

README.md
[![agentmods](https://agentmods.dev/badge/skills/jongwony/epistemic-protocols/elicit.svg)](https://agentmods.dev/skills/jongwony/epistemic-protocols/elicit)
Your own site
<a href="https://agentmods.dev/skills/jongwony/epistemic-protocols/elicit"><img src="https://agentmods.dev/badge/skills/jongwony/epistemic-protocols/elicit.svg" alt="Measured on agentmods" height="20"></a>
Per session 44 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 3,942 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. Scan, not verified.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00044 $0.03942
Opus 5 $0.00022 $0.01971
Sonnet 5 $0.00009 $0.00788
Haiku 4.5 $0.00004 $0.00394

Measured 2d ago against content hash 597dd5118c96, method: parsed. Prices are Anthropic first-party input rates as of 2026-09-06, from the pricing page.

Security

Grade A, and why

elicit scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 2d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

euporia/skills/elicit/SKILL.md · 185 lines

How it starts

The opening of the file, as written. The whole thing — 185 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Euporia Protocol

Resolve abstract aporia through Extended-Mind reverse induction. Type: (AbstractAporia, Hybrid, REVERSE-INDUCE-CYCLE, IntentSeed × ExternalizedSubstrate) → ResolvedEndpoint.

Definition

Euporia (εὐπορία): A dialogical act of opening a way through abstract aporia, where AI reverse-traces decision coordinates from the user's externalized cognitive substrate (codebase, rules, past sessions, user environment), surfaces them as cycle-emergent dimension projections, and shapes the converging intent through user answers until the endpoint resolves.

── FLOW ──
Euporia(I) → Detect(I, S) → aporia? →
  true:  (I, S, ctx) → Substrate access → ReverseTrace(I, S, ctx) → D[] →
         filter_confidence(D[]) → (D_surfaced, Λ.deferred)                              -- concrete substrate basis retained; thin-basis projections held back
         resurface(Λ.parked)                                                            -- coordinates the user could not answer yet come back as themselves
         Qs(D_surfaced, Λ.parked, cycle_n) → Stop → A → integrate(A, I) → I' →
         loop until resolved(I') ∨ A = Dismiss
  false: surface scan result; route to axis-specific protocol (axis-determined) or invite user to articulate or withdraw (substrate empty)

── MORPHISM ──
IntentSeed
  → detect(aporia, axis_undetermined)        -- verify abstract aporia exists
  → access(externalized_substrate)            -- read external substrate channels (codebase / rules / sessions / environment)
  → observe(utterance_ambiguity)              -- analyze I.utterance for in-text semantic ambiguity (Utterance channel; internal)
  → reverse_trace(coordinates)                -- infer user's externalized decision coordinates → candidate DimensionProjections
  → filter_confidence(D[]) → D_surfaced       -- retain projections whose substrate basis is concrete; hold thin-basis projections back in Λ.deferred
  → resurface(parked_coordinates)             -- bring back coordinates the user deferred in an earlier cycle, as themselves rather than re-derived
  → surface(D_surfaced, parked, cycle_emergent) -- present this cycle's projections with substrate-cited basis, alongside anything brought back
  → integrate(answer, I)                       -- update intent per user answer; ADDS determination, never revises an accepted coordinate
  → resolve(intent)                            -- convergence when user judges resolved
  → ResolvedEndpoint
requires: aporia(I)                            -- runtime checkpoint (Phase 0); sole activation precondition
deficit:  AbstractAporia                       -- activation precondition (Layer 1/2)
preserves: utterance(I)                        -- I.utterance read-only; I' accumulates substrate trace
invariant: Reverse Induction over Axis-Fixed Extraction
invariant: Coordinate Monotonicity             -- accepted coordinates are immutable (full statement: §Coordinate Monotonicity Invariant)

── TYPES ──
I              = IntentSeed { utterance: String, axis: Optional(Axis) }
I'             = Updated intent (substrate-traced + user-answered)
S              = ExternalizedSubstrate { codebase, rules, sessions, environment }
                 -- read-only view of user's externalized cognition
                 -- environment: machine-setup metadata (uname, pwd, tool versions, git config public fields)
D[]            = List(DimensionProjection)     -- cycle-emergent; no fixed taxonomy
DimensionProjection = { axis_inferred: String, coordinates: List(Coordinate) }
Coordinate     = { name: String, default: Optional(Value), question: String, basis: Evidence }
Evidence       = { source: SubstrateChannel, content: String }
SubstrateChannel ∈ {Codebase, Rules, Session, Environment, Utterance}
                 -- Codebase / Rules / Session / Environment: sourced from S (ExternalizedSubstrate fields)
                 -- Utterance: sourced from I.utterance (not a field of S; in-text semantic ambiguity of the IntentSeed itself);
                 --   citation MUST quote the actual utterance fragment, not paraphrase or attribute unstated mental models
filter_confidence = D[] → (D_surfaced, deferred)  -- partition on substrate-basis concreteness; deferred projections are re-tried on a later cycle's re-projection
D_surfaced     = List(DimensionProjection)     -- this cycle's surfaceable projections (the ones Phase 2 presents)
A              = UserAnswer ∈ {Provide(values), Defer(coords), Dismiss}   -- per-coordinate answer
                 values         = Map(Coordinate, Value)
                 coords         = Set(Coordinate) -- parked for a later cycle (covers ambiguous/partial/not-yet-answerable)
R              = ResolvedEndpoint { intent_resolved: I', residual: Set(Axis ⊎ DeferredResidual ⊎ Coordinate) }
                 -- residual members are tagged: Axis = an unresolved axis delegated to a downstream protocol; DeferredResidual = a projection the confidence filter held back; Coordinate = a coordinate the user deferred. None is reduced to a bare axis label or silently dropped
DeferredResidual = { projection: DimensionProjection, basis: Evidence }
                 -- a projection still in Λ.deferred at convergence, surfaced as residual with its substrate basis
cycle_n        = Nat                            -- current cycle counter; surfaced at every Phase 2
Phase          ∈ {0, 1, 2, 3}
Axis           = String                         -- emergent label; examples: "intent", "goal", "form", "scope", "framework"
Initiator      ∈ {UserInvoked, AIDetected}      -- bound at activation; informs Hybrid Phase 2 first-surface semantics
Qs             = Cycle-emergent surfacing interaction with D_surfaced + Λ.parked + cycle counter [Tool: Constitution interaction]

── A-BINDING ──
bind(I) = explicit_arg ∪ recent_intent_seed ∪ surfaced_aporia
Priority: explicit_arg > recent_intent_seed > surfaced_aporia

/elicit "intent"           → I = IntentSeed with utterance
/elicit (alone)            → I = most recent intent seed in session
"I want to..."             → I = utterance under discussion

If no aporia signal is detectable, Phase 0 detection surfaces the scan result instead of
proceeding to Phase 1: when the intent is fully axis-determined it routes to the matching
axis-specific protocol; when the substrate is empty it invites the user to articulate
further or withdraw.

── PHASE TRANSITIONS ──
Phase 0: I → Detect(I, S) → aporia?                                  -- detection checkpoint; aporia=true → silent proceed to Phase 1; aporia=false → surface scan result (axis-determined → routing recommendation; substrate empty → invite articulate-or-withdraw), no activation
Phase 1: (I, S, ctx) → Substrate access [Tool] → ReverseTrace [Internal] → D[] (candidate projections)
       → filter_confidence(D[]) → (D_surfaced, Λ.deferred)
       → resurface(Λ.parked)                                         -- coordinates the user deferred earlier are brought back as themselves, not re-derived
       → (D_surfaced, Λ.parked)
Phase 2: (D_surfaced, Λ.parked, cycle_n, initiator) → Qs(D_surfaced, Λ.parked, cycle_n) → Stop → A   -- Constitution; cycle counter visible
                                                                       -- Hybrid contract: cycle_n=1 ∧ initiator=AIDetected → first surfacing = implicit confirm-or-decline
Phase 3: A → integrate(A, I) → I'                                    -- track, residual identification; integrate ADDS only

Phase 0 → Phase 1: aporia(I) = true                                                          -- aporia confirmed → silent re-projection loop opens
Phase 0 → deactivate: aporia(I) = false                                                      -- no aporia signal → surface scan result (axis-determined routing recommendation OR articulate-or-withdraw), no activation
Phase 1 → Phase 2: always                                                                    -- every cycle hands the turn to the user, including one whose trace surfaced nothing new
Phase 2 → Phase 3: A received                                                                -- per-coordinate answer accepted
Phase 3 → Phase 1: ¬user_judges_resolved(I') ∧ A ≠ Dismiss → cycle_n += 1                    -- re-projection: re-trace the substrate with accumulated I'; accepted coordinates carried forward unchanged, parked coordinates re-surfaced as themselves
Phase 3 → converge: user_judges_resolved(I')                                                 -- user constitutive judgment → ResolvedEndpoint + per-cycle coordinate trace; residual folded per LOOP
Phase 3 → converge (residual): A = Dismiss                                                   -- ResolvedEndpoint with residual annotated for downstream delegation (unresolved axes; residual folded per LOOP; it may be empty)

── LOOP ──
Every termination below folds the same two leftovers into residual before returning: each projection still in Λ.deferred (as a DeferredResidual) and each coordinate still in Λ.parked (as itself). Neither is ever silently dropped.
If user_judges_resolved(I'): terminate, return ResolvedEndpoint.
If A = Dismiss: terminate with ResolvedEndpoint (residual annotated; it may be empty).
Else: cycle_n += 1, return to Phase 1 (re-project: re-trace the substrate with accumulated I'; accepted coordinates carried forward unchanged; parked coordinates re-surfaced as themselves).
No fixed cycle cap.
Convergence presentation (relay, extension-classified; at termination):
  (a) Intent readback — plain single-sentence form of resolved I' assembled from coordinate values, in user-facing language;
  (b) Per-cycle coordinate trace — for each cycle, show (D_surfaced → A → I').
Convergence is demonstrated, not asserted; the readback materializes I' as a recognizable target without adding a separate constitutive gate.
Mid-cycle scope: Intent readback (a) also surfaces in Phase 2 from cycle_n ≥ 2 (see Phase 2 surfacing format); the per-cycle coordinate trace (b) is termination-only.

── CONVERGENCE ──
resolved(I') = user_judges_resolved(I')  -- residual folded per LOOP

── TOOL GROUNDING ──
-- Realization: Constitution → TextPresent+Stop; Extension → TextPresent+Proceed
Phase 0 Detect       (sense)        → Internal analysis (no external tool)
Phase 0 Surface      (extension)    → TextPresent+Proceed (aporia=false: surface scan result; routing recommendation when axis-determined, or invite articulate-or-withdraw when substrate empty; no activation, no constitutive gate)
Phase 1 Substrate    (observe)      → artifact read, artifact search, environment run (read-only substrate access — codebase / rules / session history / Environment queries: machine-setup metadata only — uname, pwd, version probes, git config public fields). Immutable read: substrate is never mutated
Phase 1 Utterance    (sense)        → Internal analysis of I.utterance for in-text semantic ambiguity (citation quotes actual utterance fragments only)
Phase 1 ReverseTrace (sense)        → Internal analysis (axis inference + coordinate construction → candidate DimensionProjections)
Phase 1 filter_confidence (track)   → Internal state update (extension — retain projections whose substrate basis is concrete in Λ.D_surfaced; hold thin-basis projections back in Λ.deferred for a later cycle. Relay: the partition is grounded in whether a citable substrate basis exists, never a user gate)
Phase 1 resurface    (track)        → Internal state update (extension — bring each coordinate in Λ.parked back into this cycle's surfacing as itself, carrying the question and basis it was parked with. Relay: the user already asked for it to come back, so there is nothing to gate)
Phase 2 Qs           (constitution) → present (mandatory; cycle-emergent dimension options from D_surfaced + any re-surfaced parked coordinates + substrate-cited basis + cycle counter)
Phase 3              (track)        → Internal state update (integrate ADDS coordinate determination to I'; accepted coordinates never revised; Defer moves coordinates into Λ.parked, Provide removes them)
converge             (extension)    → TextPresent+Proceed (intent readback + per-cycle coordinate trace; proceed with ResolvedEndpoint)
Seam transition to declared next protocol (extension) → TextPresent+Proceed (fires at deactivation/handoff: a user-declared chain naming the next protocol settles the next move — proceed directly to it, citing that settling source. This protocol declares no wired outbound continuation edge, so the second trigger is vacuously absent. Every Constitution gate inside this protocol and inside the next protocol fires unchanged)

── MODE STATE ──
Λ = { phase: Phase, I: IntentSeed, I': IntentSeed, S: ExternalizedSubstrate,
      cycle_n: Nat,
      D_surfaced: List<DimensionProjection>,           -- this cycle's surfaceable projections (the only ones presented at Phase 2)
      deferred: Set(DimensionProjection),              -- projections held back by the confidence filter for lack of a concrete substrate basis; re-tried on a later cycle's Phase 3 → Phase 1 re-projection; surfaced as residual at every termination
      parked: Set(Coordinate),                         -- coordinates the user answered Defer on. Entered by Defer(coords), left only when that coordinate is later answered with Provide. Re-surfaced as itself at every subsequent Phase 2 — not re-derived, because the user already saw the question and said not yet. Folded into residual as itself at every termination. Kept apart from deferred above: different reason (the user could not answer vs. the substrate could not ground it) and different return path (comes back every cycle as itself vs. re-derived on a later re-projection)
      accepted_coords: Set(Coordinate),                -- monotone accumulator — once a coordinate is answered (Provide), it enters here and is NEVER removed or revised
      initiator: Initiator,
      residual: Set(Axis ⊎ DeferredResidual ⊎ Coordinate),   -- Axis members = delegated unresolved axes; DeferredResidual members = projections the confidence filter held back; Coordinate members = user-deferred coordinates. All three folded in at every termination
      active: Bool, cause_tag: String }
-- Monotonicity invariant: accepted_coords is accumulate-only across cycles — integrate(A, I) may ADD to accepted_coords, never remove or overwrite an entry (full statement in §Coordinate Monotonicity Invariant)
-- Leftover invariant: parked ∩ accepted_coords = ∅ — a coordinate is either still waiting on the user or already answered, never both. Provide moves it across; nothing moves it back

── COMPOSITION ──
*: product — (D₁ × D₂) → (R₁ × R₂). Substrate channel resolution emergent via session context.

Read the full file on GitHub · 185 lines

Files

What ships with it

1 file beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 2d ago Changed · -5 lines 597dd5118c96
  2. 6d ago First seen · 190 lines · 44 tokens per session scan A 7dbea5f5f1c0

Subscribe to this mod's changes

elicit is a skill published in the GitHub repository jongwony/epistemic-protocols (160 stars, last pushed today), licensed MIT. It adds 44 tokens to every session and 3,942 once invoked, about $0.0002 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.