Custom events, tags and debug mode

View as Markdown

Telltale for MCP servers and Telltale for APIs record every agent call with no content. Three extras help you read that record: tags on each call (which plan, which region), custom events for moments in your own product (a report exported, a plan upgraded), and debug mode to see what the SDK sends while you set it up. All three stay shape-only: Telltale never receives a message, an argument, a body or free text.

Tags

A tag is a category you attach to each call, so you can filter Tools › All tools by it, for example "how do Pro accounts' calls fail?".

JavaScript
// MCP server
const telltale = withTelltale(server, {
  endpoint: 'https://app.trytelltale.dev',
  serverKey: process.env.TELLTALE_SERVER_KEY,
  identify: ({ authInfo }) => ({ accountId: authInfo?.extra?.accountId }),
  tags: ({ authInfo }) => ({ plan: authInfo?.extra?.plan, region: 'eu', beta: false }),
});

// API middleware
const telltale = createTelltaleApi({
  endpoint: 'https://app.trytelltale.dev',
  serverKey: process.env.TELLTALE_SERVER_KEY,
  tags: req => ({ plan: req.user?.plan }),
});

Tags are categories, so the rules are strict. The SDK applies them before sending and the server applies them again:

An invalid tag is dropped on its own; the call is still recorded. The answer to each batch counts them (tagsDropped), and debug mode logs the number (never the value). Tags ride on MCP calls and on API calls with agent evidence; the per-route counts of all API calls carry no tags.

Custom events

A custom event is a named moment in your product. Telltale counts it per day and per account; it never stores a message or payload, so there is nothing in it to leak.

JavaScript
// After a report export succeeds, in a tool handler or anywhere on your server:
telltale.event('report.exported', { accountId: 'acct_42', tags: { format: 'csv' } });

Tools › All tools › Custom events shows each name with how many times it happened, how many accounts it reached, by channel and by tag value.

Without the SDK, POST to the server API with the Site's server key. Here eventId and at are required: eventId is your own unique ID for the event (8 to 128 letters, digits, _ or -) and at is when it happened, in epoch milliseconds within the last 7 days (the example uses the current time):

Shell
curl -X POST https://app.trytelltale.dev/api/v1/events \
  -H "Authorization: Bearer $TELLTALE_SERVER_KEY" -H "Content-Type: application/json" \
  -d '{"events":[{"eventId":"evt_8f2a91c0d3","name":"report.exported","at":'"$(date +%s000)"',"accountId":"acct_42","tags":{"format":"csv"}}]}'

The answer is {accepted, replayed, rejected, tagsDropped?}. Any field other than eventId, name, at, accountId, userId, channel and tags is refused (a message or payload field rejects that event), so free text cannot be stored by mistake. Custom-event rows for an account are erased with the account and included in its subject export.

Tool performance and notices

Tools › All tools lists every MCP tool and API route with its agent calls, failures, error rate and time (p50 is the typical call, p95 the slow end: one call in twenty is slower), split by agent client. Filter by client or by a tag. For an API route you also see all calls, including callers we could not confirm as agents (Unknown, which is not the same as a person); those times are "at most" figures, the upper edge of a time band.

These notices reach the bell and your webhooks:

All carry counts, the tool or route and your own account ID, never content. See Webhooks for the payloads.

Debug mode

Debug mode shows what the SDK does while you set it up. It writes to stderr (never stdout, which a stdio MCP server uses for the protocol), or to your own function. It stays in your process: the SDK sends no diagnostics about itself anywhere, debug or not.

JavaScript
withTelltale(server, { endpoint, serverKey, debug: true });               // stderr
createTelltaleApi({ endpoint, serverKey, debug: line => logger.debug(line) }); // your logger

Or set TELLTALE_DEBUG=1 in the environment without changing code. Lines look like:

Code
[telltale-mcp] debug on: sending shapes only to https://telltale.example.com | protected tools: 1 | why field on: 0 tools | batches every 5000 ms
[telltale-mcp] queued call export_report ok 182 ms | account: yes | user: yes | session: transport | tags: plan
[telltale-mcp] sent 12 calls: accepted 12 replayed 0 rejected 0
[telltale-api] queued call POST /v1/invoices 201 41 ms | account: yes | user: no | agent evidence: ip,declared | tags: plan

A debug line carries shapes only: the tool or route, the outcome, the time, whether an account and user were named, which tag keys were sent. Never arguments, results, bodies, headers, account or user IDs, tag values or keys. Turn it off in production; it is off by default.