{"_id":"@appfigures/agent-toolkit","name":"@appfigures/agent-toolkit","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@appfigures/agent-toolkit","version":"1.0.0","description":"Give your AI agents a read on the app market — download and revenue estimates, reviews, ranks, keywords, ads, and audience for any app on any major store. Agent tools for the Vercel AI SDK, OpenAI, and LangChain, plus a typed SDK client.","type":"module","sideEffects":false,"license":"Apache-2.0","author":{"name":"Appfigures"},"keywords":["appfigures","ai","agent","tools","ai-sdk","app-intelligence","app-store","aso","analytics","reviews","ratings","estimates","mobile","ios","android"],"repository":{"type":"git","url":"git+https://github.com/appfigures/agent-toolkit.git"},"homepage":"https://github.com/appfigures/agent-toolkit#readme","bugs":{"url":"https://github.com/appfigures/agent-toolkit/issues"},"publishConfig":{"access":"public"},"engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./ai":{"types":"./dist/ai.d.ts","default":"./dist/ai.js"},"./openai":{"types":"./dist/openai.d.ts","default":"./dist/openai.js"},"./langchain":{"types":"./dist/langchain.d.ts","default":"./dist/langchain.js"}},"dependencies":{"fuzzysort":"^3.1.0","temporal-polyfill":"^1.0.3","zod":"4.4.3"},"peerDependencies":{"@langchain/core":"^1","ai":"^7","openai":"^7"},"peerDependenciesMeta":{"@langchain/core":{"optional":true},"ai":{"optional":true},"openai":{"optional":true}},"gitHead":"a83698fe5de5c90f3e4a56bc1afcf4abbf99b6e7","_id":"@appfigures/agent-toolkit@1.0.0","_nodeVersion":"24.11.0","_npmVersion":"11.6.1","dist":{"integrity":"sha512-+jT7+z1DK2ybCxC8PROMVzxaS580R0y8lmWBHdoTfWAp2hK8865SYpPMSIdamBz9cJjqLPwuN2J1+FoECE54yg==","shasum":"882ee0a04c58c5c53da02644df608373d903a8e9","tarball":"https://registry.npmjs.org/@appfigures/agent-toolkit/-/agent-toolkit-1.0.0.tgz","fileCount":31,"unpackedSize":829246,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDbnhc9NFla1ignQ9xyfaQLnzUokQ0xwi4UqNKIymwC6wIgdDhddgy8ETdyKvjdmPpg763akGj62t1H+2NuI79U1eM="}]},"_npmUser":{"name":"oztune","email":"oztune+npm@gmail.com"},"directories":{},"maintainers":[{"name":"appfigures-admin","email":"opensource@appfigures.com"},{"name":"oztune","email":"oztune+npm@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/agent-toolkit_1.0.0_1787192589274_0.2596052953064649"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-20T02:23:09.163Z","1.0.0":"2026-08-20T02:23:09.439Z","modified":"2026-08-20T02:23:09.615Z"},"maintainers":[{"name":"appfigures-admin","email":"opensource@appfigures.com"},{"name":"oztune","email":"oztune+npm@gmail.com"}],"description":"Give your AI agents a read on the app market — download and revenue estimates, reviews, ranks, keywords, ads, and audience for any app on any major store. Agent tools for the Vercel AI SDK, OpenAI, and LangChain, plus a typed SDK client.","homepage":"https://github.com/appfigures/agent-toolkit#readme","keywords":["appfigures","ai","agent","tools","ai-sdk","app-intelligence","app-store","aso","analytics","reviews","ratings","estimates","mobile","ios","android"],"repository":{"type":"git","url":"git+https://github.com/appfigures/agent-toolkit.git"},"author":{"name":"Appfigures"},"bugs":{"url":"https://github.com/appfigures/agent-toolkit/issues"},"license":"Apache-2.0","readme":"# @appfigures/agent-toolkit\n\n[![npm version](https://img.shields.io/npm/v/@appfigures/agent-toolkit.svg)](https://www.npmjs.com/package/@appfigures/agent-toolkit) [![License](https://img.shields.io/badge/license-Apache_2.0-blue.svg)](./LICENSE) [![types included](https://img.shields.io/badge/types-included-blue.svg)](#the-client-for-code-your-agent-writes)\n\nGive your AI agent a read on the app market. This toolkit connects it to Appfigures: download and revenue estimates, reviews, rankings, keywords, and ads for any app on any major store, not just your own.\n\nAsk it things like:\n\n- _\"How many downloads and how much revenue is Spotify pulling in?\"_\n- _\"Is Headspace growing or shrinking over the last six months?\"_\n- _\"Who's advertising on 'meditation', and how dominant are they?\"_\n- _\"What keywords does Duolingo rank for that we don't?\"_\n- _\"What are users complaining about in an app's newest 1-star reviews?\"_\n- _\"Who actually uses ChatGPT: their age, gender, and what else they use?\"_\n\n[More recipes →](./docs/recipes.md)\n\nSetting it up with a coding agent? Point it at [`llms.txt`](./llms.txt): the doc map for wiring this into your agent.\n\n## Quickstart\n\n```sh\nnpm install @appfigures/agent-toolkit\n```\n\n```ts\nimport { AppfiguresAgentClient } from '@appfigures/agent-toolkit'\n\nconst af = new AppfiguresAgentClient() // reads APPFIGURES_API_KEY\nconst { results } = await af.apps.search({ q: 'spotify', count: 1 })\nconsole.log(results[0]) // name, downloads_last_month, revenue_last_month_usd, storefronts …\n```\n\nGet an API key at https://appfigures.com/developers/keys, then set it as `APPFIGURES_API_KEY` (or pass `apiKey` in code).\n\n**What a key can see.** Estimates, ratings, reviews, ranks, keywords, and catalog data work for any app on any store, your own or a competitor's. Store-reported numbers for your own apps (actual sales, revenue, subscriptions, and ad spend) require linking that app's store account to Appfigures, or being granted access to it.\n\n## Four ways to use it\n\nBring Appfigures into your agent however it's built — as tools it calls, code it writes, a CLI, or over MCP. The actions and their JSON-serializable shape are identical across all four.\n\n- **Agent tools** — your agent calls Appfigures actions as tools while it runs. AI SDK, OpenAI, LangChain. → [Add the tools](#tools-for-your-agent-framework)\n- **The client** — your agent writes code that queries Appfigures and gets typed data back. → [Use the client](#the-client-for-code-your-agent-writes)\n- **CLI** — run Appfigures from a terminal or a sandbox. → [`@appfigures/cli`](https://www.npmjs.com/package/@appfigures/cli)\n- **MCP** — connect Appfigures to Claude Desktop or Cursor. → [`npx @appfigures/cli mcp`](https://www.npmjs.com/package/@appfigures/cli)\n\n## What your agent can do\n\n- **App performance** — download and revenue estimates, and any numeric metric, for your apps or a competitor's.\n- **Reviews and ratings** — read reviews, break them down by rating or version, post developer replies.\n- **Store presence** — rank history, top charts, full store listings, featured placements.\n- **Keywords and ASO** — the organic and paid keywords an app ranks for, competitor ad spend, related terms, rank tracking.\n- **Audience** — age and gender estimates, and the other apps your users use.\n- **Apple Ads** — campaigns, ad groups, keywords, search terms, performance reports.\n- **App catalog** — search and aggregate across millions of apps on every major store.\n\nEvery action, with its parameters, is in the [action reference](#action-reference).\n\n## Tools for your agent framework\n\nOne tool per action. Reads run on their own. Writes wait for your approval.\n\nBuild the action surface once with `createAppfiguresActions`, then adapt it to your framework's tools with `toAISDKTools`, `toOpenAITools`, or `toLangChainTools`. The surface holds your API key and options; each adapter is a thin projection of it.\n\nInstall your framework's SDK next to the toolkit: `ai` and a model provider such as `@ai-sdk/openai` for the Vercel AI SDK, `openai` for OpenAI, or `@langchain/core @langchain/langgraph` for LangChain.\n\n### Vercel AI SDK\n\n<!-- BEGIN example: ai-sdk -->\n\n```ts\nimport { createAppfiguresActions } from '@appfigures/agent-toolkit'\nimport { toAISDKTools } from '@appfigures/agent-toolkit/ai'\nimport { generateText, stepCountIs, type LanguageModel } from 'ai'\n\n// `model` is your provider's model, e.g. `openai('gpt-4o')` from `@ai-sdk/openai`.\nexport async function run(model: LanguageModel) {\n\tconst { tools } = toAISDKTools(createAppfiguresActions()) // reads APPFIGURES_API_KEY from env\n\tconst { text } = await generateText({\n\t\tmodel,\n\t\ttools,\n\t\tstopWhen: stepCountIs(10),\n\t\tprompt: 'What are the latest downloads and revenue for Spotify?',\n\t})\n\treturn text\n}\n```\n\n<!-- END example: ai-sdk -->\n\n### OpenAI\n\nThe OpenAI SDK doesn't run tools for you. Call `handleToolCall` for each one, and loop until the model stops calling tools:\n\n<!-- BEGIN example: openai -->\n\n```ts\nimport { createAppfiguresActions } from '@appfigures/agent-toolkit'\nimport { toOpenAITools } from '@appfigures/agent-toolkit/openai'\nimport OpenAI from 'openai'\nimport type { ChatCompletionMessageParam } from 'openai/resources'\n\n// The OpenAI SDK doesn't run tools for you: call handleToolCall for each and loop until it stops.\nconst client = new OpenAI() // reads OPENAI_API_KEY from env\nconst { tools, handleToolCall } = toOpenAITools(createAppfiguresActions()) // reads APPFIGURES_API_KEY\n\nconst messages: ChatCompletionMessageParam[] = [\n\t{ role: 'user', content: 'What are the latest downloads and revenue for Spotify?' },\n]\n\nwhile (true) {\n\tconst { message } = (await client.chat.completions.create({ model: 'gpt-4o', messages, tools }))\n\t\t.choices[0]!\n\tmessages.push(message)\n\tif (!message.tool_calls?.length) break\n\tfor (const call of message.tool_calls) messages.push(await handleToolCall(call))\n}\n```\n\n<!-- END example: openai -->\n\n### LangChain\n\nBind the tools to your LangChain chat model:\n\n<!-- BEGIN example: langchain -->\n\n```ts\nimport { createAppfiguresActions } from '@appfigures/agent-toolkit'\nimport { toLangChainTools } from '@appfigures/agent-toolkit/langchain'\nimport type { BaseChatModel } from '@langchain/core/language_models/chat_models'\n\n// `model` is your LangChain chat model, e.g. from `@langchain/openai`. For an automatic tool loop,\n// hand `tools` to `createReactAgent` from `@langchain/langgraph` instead.\nexport async function run(model: BaseChatModel) {\n\tconst { tools } = toLangChainTools(createAppfiguresActions()) // reads APPFIGURES_API_KEY from env\n\treturn model.bindTools!(tools).invoke('What are the latest downloads and revenue for Spotify?')\n}\n```\n\n<!-- END example: langchain -->\n\nEvery tool returns one of:\n\n- `{ data }` on success. A `hints` field comes along when there's a caveat (see [Configuration](#configuration)).\n- `{ error }` on a handled failure, shaped for the model to fix its input and retry. An unapproved write is one of these, with `error.causeType === 'refusal'`.\n- `{ error }` with `causeType: 'unexpected'` on a bug. The model gets a sanitized `internal error in <tool>` message and a hint to retry once, then degrade. The real error goes to `onUnexpectedError` (a `createAppfiguresActions` option), never to the model.\n\nFor a framework these adapters don't cover, drive the action surface directly: `actions.list()` gives you the tool metadata to register, and `actions.execute({ path, input, signal })` runs one. If your agent writes code instead, the client below runs anywhere.\n\nThe full tools reference is in [`docs/tools-api.md`](./docs/tools-api.md): the write gate, results, scoping, and per-request auth.\n\n## The client for code your agent writes\n\nTools are for an agent running inside a framework. But an agent also writes code: scripts, scheduled jobs, one-off analyses. For those, use the client. It calls Appfigures directly and returns typed data. Where a tool returns `{ data }` or `{ error }`, the client returns the data itself and throws on failure.\n\nIt's the same actions as the tools, called as methods:\n\n```ts\nimport { AppfiguresAgentClient } from '@appfigures/agent-toolkit'\n\nconst af = new AppfiguresAgentClient({ apiKey: process.env.APPFIGURES_API_KEY })\n\nconst { results } = await af.apps.search({ q: 'spotify', count: 1 })\nconst spotify = results[0]\n// spotify.name, spotify.downloads_last_month, spotify.revenue_last_month_usd, spotify.storefronts …\n\nconst tracked = await af.apps.tracked() // no required input\n```\n\nThe first draft runs, because:\n\n- **Data is the return value.** `console.log(await af.metrics.query(…))` prints the data. There's no envelope to unwrap.\n- **Fully type-safe.** Inputs and results are typed, so a wrong call fails to compile.\n- **One error type.** Every failure throws `AppfiguresActionError`, with `causeType`, `action`, `suggestedActions`, and `hints`. Catch it with `isAppfiguresActionError`, not `instanceof`.\n\nThe full client reference is in [`docs/client-api.md`](./docs/client-api.md): returned data, errors, hints, and authentication.\n\n## Configuration\n\nEvery option has a safe default, so none of this is required to start.\n\n- **Hints** — a caveat that rides with the result: truncated data, another page, a deprecated action. Tools read them inline; the client prints them to `stderr`. → [client](./docs/client-api.md#receive-hints) · [tools](./docs/tools-api.md#handle-a-result)\n- **Approve writes** — every write refuses until you approve it, so a prompt-injected `reviews.reply` never posts. → [tools-api.md](./docs/tools-api.md#approve-writes)\n- **Scope the surface** — expose only the actions you choose, by path or group wildcard. → [tools-api.md](./docs/tools-api.md#scope-which-actions-are-exposed)\n- **Bring your own transport** — customize the built-in one (retries, a proxy, a non-production base URL) or replace it outright. → [client](./docs/client-api.md#configure-authentication) · [tools](./docs/tools-api.md#configure-authentication)\n- **Authenticate each request** — build the surface once and vary credentials per call, for a server serving many users. → [tools-api.md](./docs/tools-api.md#authenticate-each-request)\n\n## Action reference\n\nFull parameters and examples for each action are in [`docs/api-reference.md`](./docs/api-reference.md). The tools mirror these as `apps_get`, `metrics_query`, and so on.\n\n<!-- BEGIN auto-generated API REFERENCE -->\n\n### apps\n\n- [**`af.apps.search`**](./docs/api-reference.md#af-apps-search) — Find apps by name or publisher.\n- [**`af.apps.tracked`**](./docs/api-reference.md#af-apps-tracked) — List the apps your Appfigures account tracks.\n- [**`af.apps.get`**](./docs/api-reference.md#af-apps-get) — Get an app's record: basic metadata (name, developer, etc) and, if the user tracks it, what data they can access.\n\n### explorer\n\n- [**`af.explorer.listProducts`**](./docs/api-reference.md#af-explorer-listProducts) — Read catalog fields for one app or many.\n- [**`af.explorer.aggregateProducts`**](./docs/api-reference.md#af-explorer-aggregateProducts) — Aggregate across the full catalog of millions of products across Apple, Google Play, Amazon, and other major stores: counts, averages, min/max, and histograms over any set of matching products.\n- [**`af.explorer.describeFields`**](./docs/api-reference.md#af-explorer-describeFields) — List the catalog fields and the current user's access level for each.\n\n### metrics\n\n- [**`af.metrics.query`**](./docs/api-reference.md#af-metrics-query) — Query any numeric dataset for one or more apps.\n- [**`af.metrics.describeDatasets`**](./docs/api-reference.md#af-metrics-describeDatasets) — List every numeric dataset `af.metrics.query` accepts, one row per dataset with its value type and whether it's limited to your own apps.\n\n### store\n\n- [**`af.store.appRanks`**](./docs/api-reference.md#af-store-appRanks) — Trace rank history for one or more apps across countries, device types, category subtypes, and categories, as time-series positions with day-over-day deltas.\n- [**`af.store.topCharts`**](./docs/api-reference.md#af-store-topCharts) — List the top apps in a category chart for a given country and category, with current positions and day-over-day deltas.\n- [**`af.store.categories`**](./docs/api-reference.md#af-store-categories) — List every store category with its ID.\n- [**`af.store.featured`**](./docs/api-reference.md#af-store-featured) — List featured and editorial placements for an app or storefront product.\n- [**`af.store.appListing`**](./docs/api-reference.md#af-store-appListing) — Read the full store listing for one storefront: localized text (name, subtitle, description, release notes) plus screenshots, video, categories, monetization, supported devices, country availability, price, file size, and age rating.\n\n### audience\n\n- [**`af.audience.demographics`**](./docs/api-reference.md#af-audience-demographics) — Read an app's audience demographics: the estimated age and gender breakdown.\n- [**`af.audience.crossUsage`**](./docs/api-reference.md#af-audience-crossUsage) — Find the apps that an app's users also use.\n\n### reviews\n\n- [**`af.reviews.list`**](./docs/api-reference.md#af-reviews-list) — Read individual reviews for one or more apps.\n- [**`af.reviews.breakdown`**](./docs/api-reference.md#af-reviews-breakdown) — Aggregate review counts for one or more apps, bucketed by dimension.\n- [**`af.reviews.reply`**](./docs/api-reference.md#af-reviews-reply) — Post or withdraw a developer response on a specific review. _(write)_\n\n### keywords\n\n- [**`af.keywords.organic`**](./docs/api-reference.md#af-keywords-organic) — Check the organic keywords one or more apps rank for, with position, popularity, and competitiveness.\n- [**`af.keywords.paid`**](./docs/api-reference.md#af-keywords-paid) — List the paid keywords one or more apps run ads on, with impression share and organic rank.\n- [**`af.keywords.trackedRanks`**](./docs/api-reference.md#af-keywords-trackedRanks) — View where all your tracked keywords rank for a single app+country combo, with each keyword's current position, movement since it last changed, starting position, popularity, and competitiveness.\n- [**`af.keywords.trackedTrend`**](./docs/api-reference.md#af-keywords-trackedTrend) — Trace how one tracked keyword's rank changes over time for a single app+country combo.\n- [**`af.keywords.suggestions`**](./docs/api-reference.md#af-keywords-suggestions) — Discover keyword ideas to consider targeting for a single app+country combo, ranked by relevance to the app and including some drawn from apps you compete with.\n- [**`af.keywords.rankingApps`**](./docs/api-reference.md#af-keywords-rankingApps) — List the apps ranking for a specific keyword in organic search, plus the keyword's own popularity and competitiveness scores.\n- [**`af.keywords.advertisers`**](./docs/api-reference.md#af-keywords-advertisers) — List the apps advertising on a specific keyword, with each advertiser's impression share, organic rank, and how long they've been bidding.\n- [**`af.keywords.related`**](./docs/api-reference.md#af-keywords-related) — Find keywords related to a seed term for ASO research.\n- [**`af.keywords.tracked`**](./docs/api-reference.md#af-keywords-tracked) — List tracked keywords with their opaque IDs.\n- [**`af.keywords.track`**](./docs/api-reference.md#af-keywords-track) — Track a keyword to monitor your app's hourly rank for it over time and get automatic alerts when its position moves. _(write)_\n- [**`af.keywords.untrack`**](./docs/api-reference.md#af-keywords-untrack) — Stop tracking a keyword. _(write)_\n\n### appleAds\n\n- [**`af.appleAds.organizations`**](./docs/api-reference.md#af-appleAds-organizations) — List the Apple Ads organizations you manage campaigns in, with each one's currency and timezone.\n- [**`af.appleAds.campaigns`**](./docs/api-reference.md#af-appleAds-campaigns) — List your Apple Ads campaigns with each one's status, budget, targeted countries, and schedule.\n- [**`af.appleAds.adGroups`**](./docs/api-reference.md#af-appleAds-adGroups) — List Apple Ads ad groups with each one's default bid, CPA cap, pricing model, and schedule.\n- [**`af.appleAds.keywords`**](./docs/api-reference.md#af-appleAds-keywords) — List a campaign's bid keywords with each keyword's performance (impressions, taps, installs, spend, cost-per-install) over a date range, plus its match type, bid, and whether it's a targeting or negative term.\n- [**`af.appleAds.searchTerms`**](./docs/api-reference.md#af-appleAds-searchTerms) — List the actual user search terms that triggered a campaign's ads, each with its all-time performance (impressions, taps, installs, spend, cost-per-install).\n- [**`af.appleAds.report`**](./docs/api-reference.md#af-appleAds-report) — Report Apple Ads performance per campaign (impressions, taps, installs, spend, cost-per-install), plus an account-wide total, over a date range.\n- [**`af.appleAds.topKeywords`**](./docs/api-reference.md#af-appleAds-topKeywords) — Rank a campaign's top-performing keywords by conversion rate, spend, and installs over a date range.\n\n### sdks\n\n- [**`af.sdks.list`**](./docs/api-reference.md#af-sdks-list) — List every known SDK with its id, or search to find a specific one.\n\n<!-- END auto-generated API REFERENCE -->\n\n## Reference guides\n\nIn [`docs/`](./docs):\n\n- [`docs/api-reference.md`](./docs/api-reference.md) — every action's params, types, and examples\n- [`docs/client-api.md`](./docs/client-api.md) — the typed client: calling actions, returned data, errors, hints, `signal`, authentication\n- [`docs/tools-api.md`](./docs/tools-api.md) — the action surface and framework adapters: the write gate, results, scoping, per-request auth\n- [`docs/recipes.md`](./docs/recipes.md) — worked recipes: real, multi-step flows shown as client calls\n- [`docs/catalog_playbook.md`](./docs/catalog_playbook.md) — the `af.explorer.*` query grammar and field list\n- [`docs/numeric_metrics.md`](./docs/numeric_metrics.md) — the datasets `af.metrics.query` accepts\n- [`docs/glossary.md`](./docs/glossary.md) — key terms\n\nAn agent wired with the framework tools can fetch the last three at runtime via the `docs_get` tool.\n\n## Examples\n\nClient scripts in [`examples/client/`](./examples/client), each a real solution against live data. Run one with `npx tsx examples/client/<file>`:\n\n- [`app-stats.ts`](./examples/client/app-stats.ts) — one app's downloads, revenue, 6-month trend, and rating spread.\n- [`competitor-report.ts`](./examples/client/competitor-report.ts) — rank several apps head-to-head by last-month downloads and revenue.\n- [`keyword-competition.ts`](./examples/client/keyword-competition.ts) — who ranks organically and who advertises on a keyword, plus related terms to target.\n- [`review-triage.ts`](./examples/client/review-triage.ts) — an app's 1–2★ reviews by version and country, and the newest ones awaiting a reply.\n- [`audience-overlap.ts`](./examples/client/audience-overlap.ts) — an app's age and gender split, and the apps its audience shares.\n\nTool-wiring for each framework in [`examples/tools/`](./examples/tools), matching the snippets [above](#tools-for-your-agent-framework):\n\n- [`openai-tools.ts`](./examples/tools/openai-tools.ts) — the OpenAI tool-call loop, runnable end-to-end with an OpenAI key.\n- [`ai-sdk-tools.ts`](./examples/tools/ai-sdk-tools.ts) — Vercel AI SDK wiring, exported as `run(model)` so you pass your provider's model.\n- [`langchain-tools.ts`](./examples/tools/langchain-tools.ts) — LangChain wiring via `bindTools`, exported as `run(model)` for your chat model.\n\n## About this repository\n\n`@appfigures/agent-toolkit` is built from Appfigures' internal monorepo and published as a compiled bundle. The `dist/` files here are the released build, not editable source. Bug reports and feature requests are welcome in the issue tracker. Code changes are made upstream, so this repo doesn't accept pull requests.\n","readmeFilename":"README.md","_rev":"1-225ac94f26bcec80ccd3ea2a6941c07c"}