Skip to main content
A factory captures the constants every tool for one API shares — base URL, auth, casing, envelope — and returns a callable that turns a schema plus a URL template into a Tool. Defaults set on the factory can be overridden per tool.

api_key_tool_factory

Tools for an API that authenticates with static headers: x-api-key, a bearer token you already hold, several headers at once.
str | Callable[[], str]
required
Base URL for the API, e.g. "https://api.example.com/". A callable is resolved on every request.
Dict[str, str] | Callable[[], Dict[str, str]]
default:"None"
Headers injected on every request. May be omitted here and supplied per tool via api_key_headers_override; a tool with neither raises DeclarationError. An empty value in a literal mapping is rejected at build time — on the factory and on the tool.
"camel" | "snake" | "pascal" | "kebab"
default:"\"camel\""
Case convention for body keys.
"camel" | "snake" | "pascal" | "kebab"
default:"\"snake\""
Case convention for query keys.
"camel" | "snake" | "pascal" | "kebab"
default:"\"snake\""
Case convention for path keys.
int
default:"20"
Request timeout in seconds.
Optional[str]
default:"None"
Link to the API’s own rate-limit documentation. Carried onto every tool.
Optional[Envelope]
default:"None"
How this API reports failure inside a 200 response. Declared once here, enforced on every tool the factory builds.
Optional[Pagination]
default:"None"
Where this API keeps its cursor. Declare it per tool instead when only some endpoints are lists — a retrieve labelled with a cursor parameter it does not accept is worse than no declaration.
"json" | "form"
default:"\"json\""
"form" for form-encoded APIs such as Stripe and Twilio.
"repeat" | "bracket"
default:"\"repeat\""
"bracket" for APIs expecting expand[0]=x in the query string.
Optional[Dict[str, Any]]
default:"None"
Query parameters sent verbatim on every request.
Optional[Dict[str, str]]
default:"None"
Headers sent verbatim on every request — an Azure api-version, a Notion-Version.
Optional[CallSink]
default:"None"
Receives a ToolCall after every invocation of every tool this factory builds. Declared here because observability belongs to the deployment, not to one endpoint.
Optional[Iterable[int]]
default:"None"
Statuses that mean “your credential” rather than “not allowed”. Defaults to {401}.
ToolBuilder
A callable that builds Tool instances with these defaults. Its parameters are listed under the builder.

oauth_tool_factory

Tools for an API that authenticates with a bearer token. The token is fetched from credential_provider on every call, so a provider that refreshes is picked up without rebuilding the tools. Charter never runs the OAuth flow itself: a missing, expired or rejected token raises CredentialError for the host application.
The keyword parameters it shares with api_key_tool_factorybody_case, query_case, path_case, timeout, quota_doc_url, envelope, pagination, body_format, query_format, static_query, static_headers, on_call, credential_statuses — behave identically. The four that differ:
str
required
Provider identifier passed to get_credentials, e.g. "google". Also the peer.service label on every record.
CredentialProvider
required
Supplies the bearer token. See Credentials.
Optional[Sequence[str]]
default:"None"
The scopes these tools need, carried as metadata for consent screens and approval UIs. Charter does not request them.
int
default:"10"
How dead a token must be before the runtime refuses to send it. A guard against sending something already expired, not a refresh policy.

The builder

Both factories return a callable with the same parameters, except that api_key_headers_override exists only on the API-key builder and scopes_override only on the OAuth one.
Two details of how overrides resolve:
  • body_case_override, query_case_override, path_case_override, timeout_override, envelope_override, pagination_override, on_call_override, api_key_headers_override and scopes_override replace the factory value when they are not None. Passing None keeps the factory’s.
  • body_format_override is applied with or, so "json" and "form" both work but a falsy value falls back to the factory’s.
static_body is per tool rather than per factory because the constant belongs to the operation: every Linear tool POSTs to the same graphql URL, and the query document is what distinguishes one from another.

Errors