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

# Packs

A pack is a set of tools already declared against one API. Configure the
credential once and every tool in it is callable — the schemas, the wire contract,
the failure convention and the pagination style are already written down.

Doing it yourself is the slow part. One endpoint can pull in a dozen schemas that
reference each other across as many pages, sometimes on a different site, and one
field in the wrong place is a 400 you cannot reproduce. A pack is that reading
already done, from the vendor's own docs, and [checked by the conformance
suite](/charter/charter/guarantees/conformance). [Why Charter](/charter/charter/why-charter) is the longer answer
to why the gap exists at all.

## Coverage

<div className="pack-grid">
  <Columns cols={3}>
    <Card title="Gmail" icon="https://mintcdn.com/r28-ai-inc/NyChRnFOQktn9qch/charter/images/logos/gmail.svg?fit=max&auto=format&n=NyChRnFOQktn9qch&q=85&s=cbc993eafa9c9501e070adc01758213c" href="/charter/charter/packs/gmail" width="512" height="399" data-path="charter/images/logos/gmail.svg">
      23 tools · OAuth bearer
    </Card>

    <Card title="Google Calendar" icon="https://mintcdn.com/r28-ai-inc/NyChRnFOQktn9qch/charter/images/logos/gcalendar.svg?fit=max&auto=format&n=NyChRnFOQktn9qch&q=85&s=6beced9ed4b9ce811c5275e784db9340" href="/charter/charter/packs/gcalendar" width="512" height="512" data-path="charter/images/logos/gcalendar.svg">
      13 tools · OAuth bearer
    </Card>

    <Card title="Google Sheets" icon="https://mintcdn.com/r28-ai-inc/NyChRnFOQktn9qch/charter/images/logos/gsheets.svg?fit=max&auto=format&n=NyChRnFOQktn9qch&q=85&s=d0859e75dc63d0349e9b991d91001ebf" href="/charter/charter/packs/gsheets" width="74" height="100" data-path="charter/images/logos/gsheets.svg">
      17 tools · OAuth bearer
    </Card>

    <Card title="Google Docs" icon="https://mintcdn.com/r28-ai-inc/NyChRnFOQktn9qch/charter/images/logos/gdocs.svg?fit=max&auto=format&n=NyChRnFOQktn9qch&q=85&s=eac053a808e842820d45c25f9edee79d" href="/charter/charter/packs/gdocs" width="24" height="24" data-path="charter/images/logos/gdocs.svg">
      3 tools · OAuth bearer
    </Card>

    <Card title="Google Drive" icon="https://mintcdn.com/r28-ai-inc/NyChRnFOQktn9qch/charter/images/logos/gdrive.svg?fit=max&auto=format&n=NyChRnFOQktn9qch&q=85&s=8b624337f5602dc71c69980d4354408a" href="/charter/charter/packs/gdrive" width="24" height="24" data-path="charter/images/logos/gdrive.svg">
      25 tools · OAuth bearer
    </Card>

    <Card title="Google Forms" icon="https://mintcdn.com/r28-ai-inc/NyChRnFOQktn9qch/charter/images/logos/gforms.svg?fit=max&auto=format&n=NyChRnFOQktn9qch&q=85&s=1958eb86ad74f35ef13829ca2ead3ff8" href="/charter/charter/packs/gforms" width="24" height="24" data-path="charter/images/logos/gforms.svg">
      6 tools · OAuth bearer
    </Card>

    <Card title="Slack" icon="https://mintcdn.com/r28-ai-inc/NyChRnFOQktn9qch/charter/images/logos/slack.svg?fit=max&auto=format&n=NyChRnFOQktn9qch&q=85&s=7463d99968ec37e233567be8bbf73257" href="/charter/charter/packs/slack" width="2448" height="2453" data-path="charter/images/logos/slack.svg">
      18 tools · OAuth bearer
    </Card>

    <Card title="GitHub" icon="https://mintcdn.com/r28-ai-inc/NyChRnFOQktn9qch/charter/images/logos/github.svg?fit=max&auto=format&n=NyChRnFOQktn9qch&q=85&s=4f90060253a539740b2ac6051c13a3e0" href="/charter/charter/packs/github" width="24" height="24" data-path="charter/images/logos/github.svg">
      139 tools · OAuth bearer
    </Card>

    <Card title="Stripe" icon="https://mintcdn.com/r28-ai-inc/NyChRnFOQktn9qch/charter/images/logos/stripe.svg?fit=max&auto=format&n=NyChRnFOQktn9qch&q=85&s=f02f6621388931d0265a967eb63d5a0e" href="/charter/charter/packs/stripe" width="256" height="256" data-path="charter/images/logos/stripe.svg">
      59 tools · API key
    </Card>

    <Card title="Linear" icon="https://mintcdn.com/r28-ai-inc/NyChRnFOQktn9qch/charter/images/logos/linear.svg?fit=max&auto=format&n=NyChRnFOQktn9qch&q=85&s=c94cc661a76dc2f53bc834bbe26579fb" href="/charter/charter/packs/linear" width="200" height="200" data-path="charter/images/logos/linear.svg">
      128 tools · API key
    </Card>

    <Card title="Shopify" icon="https://mintcdn.com/r28-ai-inc/NyChRnFOQktn9qch/charter/images/logos/shopify.svg?fit=max&auto=format&n=NyChRnFOQktn9qch&q=85&s=5dc02be39ae735aacf61c653fe2a48b7" href="/charter/charter/packs/shopify" width="2192" height="2500" data-path="charter/images/logos/shopify.svg">
      22 tools · API key
    </Card>

    <Card title="Notion" icon="https://mintcdn.com/r28-ai-inc/NyChRnFOQktn9qch/charter/images/logos/notion.svg?fit=max&auto=format&n=NyChRnFOQktn9qch&q=85&s=250fe1d5bc900f87bacea3f7507b3478" href="/charter/charter/packs/notion" width="24" height="24" data-path="charter/images/logos/notion.svg">
      35 tools · OAuth bearer
    </Card>

    <Card title="Granola" icon="https://mintcdn.com/r28-ai-inc/NyChRnFOQktn9qch/charter/images/logos/granola.svg?fit=max&auto=format&n=NyChRnFOQktn9qch&q=85&s=aa9cf255d9506bd3f1e7a593c0c7b1cb" href="/charter/charter/packs/granola" width="200" height="200" data-path="charter/images/logos/granola.svg">
      9 tools · API key
    </Card>

    <Card title="Firecrawl" icon="https://mintcdn.com/r28-ai-inc/NyChRnFOQktn9qch/charter/images/logos/firecrawl.svg?fit=max&auto=format&n=NyChRnFOQktn9qch&q=85&s=26fc5fe81d1bc73e24a15f16b7857630" href="/charter/charter/packs/firecrawl" width="50" height="72" data-path="charter/images/logos/firecrawl.svg">
      43 tools · API key
    </Card>

    <Card title="Tavily" icon="https://mintcdn.com/r28-ai-inc/NyChRnFOQktn9qch/charter/images/logos/tavily.svg?fit=max&auto=format&n=NyChRnFOQktn9qch&q=85&s=aabc1d72cc1acf447307e405bc0ddcc5" href="/charter/charter/packs/tavily" width="24" height="24" data-path="charter/images/logos/tavily.svg">
      9 tools · API key
    </Card>
  </Columns>
</div>

Every tool in every pack has its LLM schema built, its egress map checked
against that schema, and its OpenAI function definition validated in the suite.

## Compatibility with agents

Every pack exports `TOOLS`, which is what an [adapter](/charter/charter/using/adapters) takes:

```python packs_to_langchain_tools.py theme={null}
from charter.adapters.langchain import to_langchain_tools
from charter.packs import gmail, slack

tools = to_langchain_tools([*gmail.TOOLS, *slack.TOOLS])
```

`TOOLS` is the default list, not the complete one. A pack may build tools it
leaves out.

## What the hard cases taught the runtime

<AccordionGroup>
  <Accordion title="Slack — failure arrives as HTTP 200">
    Slack reports failure as HTTP 200 with `{"ok": false, "error": "..."}`, so a
    generic HTTP client hands the model an error payload as if the message had
    sent.

    That is not patched per tool. It is declared once, as an
    [`Envelope`](/charter/charter/tools/envelopes) on the factory, and enforced by the runtime on
    every call — including calls by tools somebody adds next year. The same one
    line handles any GraphQL API, whose failures are always a 200 with an
    `errors` array. [Read more](/charter/charter/packs/slack).
  </Accordion>

  <Accordion title="Stripe — form encoding and a derived cursor">
    Form-encoded in both directions with bracket notation
    (`line_items[0][price]=…`), and a cursor that is the last object's id rather
    than a token the API hands back (`data[-1].id`). Both are declared once on
    the factory. [Read more](/charter/charter/packs/stripe).
  </Accordion>

  <Accordion title="GitHub — OAuth plus constant headers">
    A bearer token from your credential provider, alongside an `Accept`, an
    `X-GitHub-Api-Version` and a `User-Agent` that GitHub requires and the model
    must never see. Those go in `static_headers`.

    GitHub also pages by number rather than by cursor — ask for page 1, 2, 3 and
    stop when a page comes back short — which is the second pagination style
    `Pagination` declares. [Read more](/charter/charter/packs/github).
  </Accordion>

  <Accordion title="Linear and Shopify — GraphQL, and why static_body exists">
    Every tool in a GraphQL pack POSTs to the same URL. What makes `issues_list`
    different from `issue_create` is the query document, which is a constant
    belonging to the tool rather than a parameter. Putting it in `static_body`
    keeps it off the schema entirely.

    That is the whole boundary: a GraphQL endpoint accepts arbitrary documents,
    so a tool that let the model write the query would not be an integration, it
    would be a shell.

    Both packs also carry a failure GraphQL's own `errors` array does not. A
    mutation the server understood and then declined comes back HTTP 200, with no
    `errors`, and the refusal in the payload — Linear's `success: false`,
    Shopify's `userErrors`. Every signal a runtime normally trusts says the write
    happened. So `Envelope` field names are paths, with `*` standing for
    whichever operation the tool called:

    ```python theme={null}
    from charter import Envelope

    Envelope(errors_field=("errors", "data.*.userErrors"))
    ```

    Shopify additionally has no fixed host: a store lives at
    `https://{shop}.myshopify.com/`, so its base URL is resolved per request from
    `configure()` rather than being a schema field the model could point
    elsewhere. [Linear](/charter/charter/packs/linear) · [Shopify](/charter/charter/packs/shopify).
  </Accordion>
</AccordionGroup>

## Writing your own pack

Twelve packs will never cover the API you actually work with. That is the normal
case, and the answer is not to wait for a twelfth.

A pack is declarations rather than integration code, which makes writing one
small: the same
[`oauth_tool_factory`](/charter/charter/reference/factories#oauth_tool_factory) or
[`api_key_tool_factory`](/charter/charter/reference/factories#api_key_tool_factory) call that
every pack page prints in full, then one schema per endpoint.

And you mostly do not write it yourself. [The pack-writing
skill](/charter/charter/start/coding-agents#the-pack-writing-skill) is a single markdown file that gives a coding agent the order
to work in and the reading it must not skip, which is the step that decides
whether a pack is right. The [conformance suite](/charter/charter/guarantees/conformance) then
holds the result to the same rules as the eleven above.

### Improving existing packs

A pack covers the endpoints most people reach for, not all of them. When yours is
missing, `TOOLS` is an ordinary list:

```python packs_extend.py theme={null}
from charter.packs import gmail

# history_list is yours, built with the same factory the pack uses
tools = [*gmail.TOOLS, history_list]
```

If a tool already in the pack declares something wrong, write your own and leave
that one out. The runtime treats them the same. Either way the fix is worth
sending back, because the next person hits the same thing.

### Contributing it back

A pack for an API you actually use is the most useful thing anyone can add here,
and it does not need permission first. Open a
[pack request](https://github.com/r28ai/charter/issues/new?template=pack_request.yml)
so that two people do not write the same pack, then follow
[the skill file](https://github.com/r28ai/charter/blob/main/skills/writing-charter-packs/SKILL.md).
[CONTRIBUTING.md](https://github.com/r28ai/charter/blob/main/CONTRIBUTING.md)
covers the setup and the rules the suite enforces anyway.
