> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shouldertap.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Concepts

> The core building blocks of ShoulderTap — requests, proposals, experts, consumers, kinds, topics, transports, and adapters — and how they fit together.

ShoulderTap is built around a small set of concepts. Understanding how they relate makes it much easier to configure the engine, integrate an agent, and reason about the protocol. This page defines each one in plain terms.

<AccordionGroup>
  <Accordion title="Request" icon="hand-pointer">
    A **request** (`ContextRequest`, id prefix `req_`) is a consumer asking for context — a question an agent couldn't answer on its own. It carries a `kind`, a `topic`, the `question` text, the submitting `consumer`, and optional `context`, `dedup_key`, and routing overrides.

    A request moves through a lifecycle: `queued → asked → escalated → proposed → accepted | rejected | failed`. You can read a request's current status and its accepted answer at any time via `GET /requests/{id}`.
  </Accordion>

  <Accordion title="Proposal" icon="file-check">
    A **proposal** (`ContextProposal`, id prefix `prop_`) is an expert's answer, structured and attributed. It links back to its `request_id` and carries the expert's verbatim `answer`, an optional LLM-`structured` form of that answer, a `confidence` score, and `provenance` (who answered, how, and when).

    Every proposal starts as `pending` in the approval queue. A human accepts or rejects it before it is ever delivered to a consumer — unless that consumer explicitly opted into `auto_accept`.
  </Accordion>

  <Accordion title="Expert" icon="user">
    An **expert** is a human in the registry who can answer questions on one or more topics. Each expert has an `id` (their Slack user ID), a `name`, a list of `topics`, and an optional `escalation_to` — the expert to re-ask if they don't reply in time.

    Experts are defined in `shouldertap.yaml` and carry live state the engine tracks: whether they're `muted`, how many `open_asks` they have outstanding, and how many they've received today. Rate limits and quiet hours protect them from being over-asked.
  </Accordion>

  <Accordion title="Consumer" icon="robot">
    A **consumer** is anything that submits requests and receives answers — typically an AI agent, but also the CLI, the MCP server, or your own service. A consumer is identified by a string id (for example `bi.assistant`) and declares which `handles_kinds` it deals with and how it wants answers delivered.

    Consumers receive answers through **delivery**: a `webhook` POST, or an `inprocess` callback when the consumer is embedded in the same process as the engine via the SDK.
  </Accordion>

  <Accordion title="Kind" icon="shapes">
    A **kind** is the type of question being asked, and it determines the schema the expert's answer is captured into. Two kinds ship built in:

    | Kind                  | Structured shape                         |
    | --------------------- | ---------------------------------------- |
    | `glossary.definition` | `{ definition, caveats[], examples[]? }` |
    | `freeform.answer`     | `{ summary, details? }`                  |

    A consumer can register its own kind with a custom JSON Schema at registration time; a custom schema takes precedence over a built-in of the same name. If structuring fails or confidence is below 0.3, the raw `answer` is still preserved — it is never dropped.
  </Accordion>

  <Accordion title="Topic" icon="tag">
    A **topic** is the routing key that connects a request to an expert. When a request arrives, ShoulderTap normalizes its topic (lowercase, whitespace-collapsed) and matches it against each expert's `topics`.

    Routing tries, in order: an exact topic match (load-balanced to the expert with the fewest open asks), a fuzzy token-overlap match, then the topic's configured `fallback` expert. If nothing matches, the request fails with `no_expert_found`. A request can also name `target_experts` to bypass topic routing entirely.
  </Accordion>

  <Accordion title="Transport" icon="comments">
    A **transport** is how ShoulderTap reaches experts. Two are built in: `console` prints the DM to your terminal and reads replies from stdin (ideal for a first look, no Slack needed), and `slack` sends real DMs through a Slack app and captures replies from the Events API. You choose one with `shtap serve --transport`.
  </Accordion>

  <Accordion title="Adapter" icon="plug">
    An **adapter** is a consumer-side helper that writes an accepted proposal back into a system of record. Two ship with ShoulderTap: an **OpenMetadata** adapter that patches a glossary term's description with a provenance footer, and a generic **webhook** adapter that POSTs the accepted proposal anywhere. Adapters implement a single method, `on_accepted(proposal)`.
  </Accordion>
</AccordionGroup>

## Deduplication

If a request carries a `dedup_key` that matches another request from the **same consumer** within its dedup window (default 24 hours), ShoulderTap deduplicates it. If the matching request already resolved to an accepted proposal, that proposal is delivered to the new consumer immediately — no expert is asked again. If the matching request is still open, the new consumer is attached as an additional subscriber and gets the answer when it lands. An expert is never asked twice for the same thing.

<Tip>
  The fastest way to see these concepts in action is the [Quickstart](/quickstart) — you'll run a real request, proposal, expert, and approval through the console transport in about 90 seconds.
</Tip>
