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.
npx agentmods add skills/jongwony/epistemic-protocols/elicitnpx skills add jongwony/epistemic-protocols --skill elicitgit clone --depth 1 https://github.com/jongwony/epistemic-protocolsWrote 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.
[](https://agentmods.dev/skills/jongwony/epistemic-protocols/elicit)<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>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.
| Model | Per session | Once 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 |
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.
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.
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.
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.
- 2d ago Changed · -5 lines 597dd5118c96
- 6d ago First seen · 190 lines · 44 tokens per session scan A 7dbea5f5f1c0
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.
Other skills, from other repositories
taiyi-ui-design
TaiyiForge 第 4 阶段 — UI/UX 契约,产出 UI-DESIGN.md。四端通用。.
flow-next-tracker-sync
Project a flow-next spec to a tracker issue (Linear, GitHub, GitLab, Jira) and reconcile two-way. Use when asked to sync to a tracker. NOT plan-sync.
taiyi-evolve
TaiyiForge 辅助 — 实现后架构与文档同步(architecture-sync)。OpenCode / Claude / Codex / Cursor 通用。.
flow-next-resolve-pr
Resolve PR review feedback. Fetches unresolved threads, triages, fixes, replies and resolves via GraphQL. Use when asked to address review comments.
taiyi-diagram-c4
TaiyiForge 辅助 — 从代码反推 C4 架构文档(Observed/Inferred 分层 · Mermaid 真源)。OpenCode / Claude / Codex / Cursor 通用。.
writing-style
Use for technical communication - GitHub/GitLab tickets, PR/MR descriptions, issue comments, code review comments, commit messages. Direct, brief style with no AI-speak. NOT for README.md, public docs, or blog posts.