{"id":"0e1d1786-959b-451e-a473-15170ac0bb42","shortId":"WcURct","kind":"skill","title":"apollo-router-plugin-creator","tagline":"Guide for writing Apollo Router native Rust plugins. Use this skill when: (1) users want to create a new router plugin, (2) users want to add service hooks (router_service, supergraph_service, execution_service, subgraph_service), (3) users want to modify an existing router plugi","description":"# Apollo Router Plugin Creator\n\nCreate native Rust plugins for Apollo Router.\n\n## Request Lifecycle\n\n```\n┌────────┐             ┌────────────────┐                                   ┌────────────────────┐               ┌───────────────────┐       ┌─────────────────────┐\n│ Client │             │ Router Service │                                   │ Supergraph Service │               │ Execution Service │       │ Subgraph Service(s) │\n└────┬───┘             └────────┬───────┘                                   └──────────┬─────────┘               └─────────┬─────────┘       └──────────┬──────────┘\n     │                          │                                                      │                                   │                            │\n     │      Sends request       │                                                      │                                   │                            │\n     │──────────────────────────▶                                                      │                                   │                            │\n     │                          │                                                      │                                   │                            │\n     │                          │  Converts raw HTTP request to GraphQL/JSON request   │                                   │                            │\n     │                          │──────────────────────────────────────────────────────▶                                   │                            │\n     │                          │                                                      │                                   │                            │\n     │                          │                                                      │  Initiates query plan execution   │                            │\n     │                          │                                                      │───────────────────────────────────▶                            │\n     │                          │                                                      │                                   │                            │\n     │                          │                                                      │                               ┌par [Initiates sub-operation]───────┐\n     │                          │                                                      │                               │   │                            │   │\n     │                          │                                                      │                               │   │  Initiates sub-operation   │   │\n     │                          │                                                      │                               │   │────────────────────────────▶   │\n     │                          │                                                      │                               │   │                            │   │\n     │                          │                                                      │                               ├[Initiates sub-operation]╌╌╌╌╌╌╌╌╌╌╌┤\n     │                          │                                                      │                               │   │                            │   │\n     │                          │                                                      │                               │   │  Initiates sub-operation   │   │\n     │                          │                                                      │                               │   │────────────────────────────▶   │\n     │                          │                                                      │                               │   │                            │   │\n     │                          │                                                      │                               ├[Initiates sub-operation]╌╌╌╌╌╌╌╌╌╌╌┤\n     │                          │                                                      │                               │   │                            │   │\n     │                          │                                                      │                               │   │  Initiates sub-operation   │   │\n     │                          │                                                      │                               │   │────────────────────────────▶   │\n     │                          │                                                      │                               │   │                            │   │\n     │                          │                                                      │                               └────────────────────────────────────┘\n     │                          │                                                      │                                   │                            │\n     │                          │                                                      │  Assembles and returns response   │                            │\n     │                          │                                                      ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│                            │\n     │                          │                                                      │                                   │                            │\n     │                          │            Returns GraphQL/JSON response             │                                   │                            │\n     │                          ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│                                   │                            │\n     │                          │                                                      │                                   │                            │\n     │  Returns HTTP response   │                                                      │                                   │                            │\n     ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│                                                      │                                   │                            │\n     │                          │                                                      │                                   │                            │\n┌────┴───┐             ┌────────┴───────┐                                   ┌──────────┴─────────┐               ┌─────────┴─────────┐       ┌──────────┴──────────┐\n│ Client │             │ Router Service │                                   │ Supergraph Service │               │ Execution Service │       │ Subgraph Service(s) │\n└────────┘             └────────────────┘                                   └────────────────────┘               └───────────────────┘       └─────────────────────┘\n```\n\n## Service Hooks\n\n### Service Overview\n\n| Service              | Description                                                                                                                                                                                                                                                                                                                                                                                                                                           |\n|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `router_service`     | Runs at the very beginning and very end of the HTTP request lifecycle.For example, JWT authentication is performed within the RouterService.Define router_service if your customization needs to interact with HTTP context and headers. It doesn't support access to the body property                                                                                                                                                               |\n| `supergraph_service` | Runs at the very beginning and very end of the GraphQL request lifecycle.Define supergraph_service if your customization needs to interact with the GraphQL request or the GraphQL response. For example, you can add a check for anonymous queries.                                                                                                                                                                                                  |\n| `execution_service`  | Handles initiating the execution of a query plan after it's been generated.Define execution_service if your customization includes logic to govern execution (for example, if you want to block a particular query based on a policy decision).                                                                                                                                                                                                       |\n| `subgraph_service`   | Handles communication between the router and your subgraphs.Define subgraph_service to configure this communication (for example, to dynamically add HTTP headers to pass to a subgraph).Whereas other services are called once per client request, this service is called once per subgraph request that's required to resolve the client's request. Each call is passed a subgraph parameter that indicates the name of the corresponding subgraph. |\n\n**Signatures:**\n```rust\nfn router_service(&self, service: router::BoxService) -> router::BoxService\nfn supergraph_service(&self, service: supergraph::BoxService) -> supergraph::BoxService\nfn execution_service(&self, service: execution::BoxService) -> execution::BoxService\nfn subgraph_service(&self, name: &str, service: subgraph::BoxService) -> subgraph::BoxService\n```\n\n### Individual Hooks (Tower Layers)\n\nUse `ServiceBuilder` to compose these hooks within any service:\n\n| Hook                      | Purpose                                      | Sync/Async |\n|---------------------------|----------------------------------------------|------------|\n| `map_request(fn)`         | Transform request before proceeding          | Sync       |\n| `map_response(fn)`        | Transform response before returning          | Sync       |\n| `checkpoint(fn)`          | Validate/filter, can short-circuit           | Sync       |\n| `checkpoint_async(fn)`    | Async validation, can short-circuit          | Async      |\n| `buffered()`              | Enable service cloning (needed for async)    | -          |\n| `instrument(span)`        | Add tracing span around service              | -          |\n| `rate_limit(num, period)` | Control request throughput                   | -          |\n| `timeout(duration)`       | Set operation time limit                     | -          |\n\n### Choosing a Service Hook\n\n**By data needed:**\n- HTTP headers only → `router_service`\n- GraphQL query/variables → `supergraph_service`\n- Query plan → `execution_service`\n- Per-subgraph control → `subgraph_service`\n\n**By timing:**\n- Before GraphQL parsing → `router_service` request\n- After parsing, before planning → `supergraph_service` request\n- After planning, before execution → `execution_service` request\n- Before/after each subgraph call → `subgraph_service`\n- Final response to client → `router_service` response\n\nSee [references/service-hooks.md](references/service-hooks.md) for implementation patterns.\n\n## Quick Start\n\n### Step 1: Create Plugin File\n\nCreate a new file `src/plugins/my_plugin.rs` with required imports:\n\n```rust\nuse std::ops::ControlFlow;\nuse apollo_router::plugin::{Plugin, PluginInit};\nuse apollo_router::register_plugin;\nuse apollo_router::services::{router, subgraph, supergraph};\nuse schemars::JsonSchema;\nuse serde::Deserialize;\nuse tower::{BoxError, ServiceBuilder, ServiceExt};\n\nconst PLUGIN_NAME: &str = \"my_plugin\";\n```\n\n### Step 2: Define Configuration Struct\n\nEvery plugin needs a configuration struct with `Deserialize` and `JsonSchema` derives. The `JsonSchema` enables configuration validation in editors:\n\n```rust\n#[derive(Debug, Clone, Default, Deserialize, JsonSchema)]\nstruct MyPluginConfig {\n  /// Enable the plugin\n  enabled: bool,\n  // Add other configuration fields as needed\n}\n```\n\n### Step 3: Define Plugin Struct\n\n```rust\n#[derive(Debug)]\nstruct MyPlugin {\n  configuration: MyPluginConfig,\n}\n```\n\n### Step 4: Implement Plugin Trait\n\nImplement the `Plugin` trait with the required `Config` type and `new` constructor:\n\n```rust\n#[async_trait::async_trait]\nimpl Plugin for MyPlugin {\n  type Config = MyPluginConfig;\n\n  async fn new(init: PluginInit<Self::Config>) -> Result<Self, BoxError> {\n    Ok(MyPlugin { configuration: init.config })\n  }\n\n  // Add service hooks based on your needs (see \"Choosing a Service Hook\" section)\n}\n```\n\n### Step 5: Add Service Hooks\n\nChoose which service(s) to hook based on your requirements, see [Service Overview](#service-overview) for details.\n\nExample service hook:\n```rust\nfn supergraph_service(&self, service: supergraph::BoxService) -> supergraph::BoxService {\n  if !self.configuration.enabled {\n    return service;\n  }\n\n  ServiceBuilder::new()\n    .map_request(|req| { /* transform request */ req })\n    .map_response(|res| { /* transform response */ res })\n    .service(service)\n    .boxed()\n}\n```\n\n### Step 6: Register Plugin\n\nAt the bottom of your plugin file, register it with the router:\n\n```rust\nregister_plugin!(\"acme\", \"my_plugin\", MyPlugin);\n```\n\n### Step 7: Add Module to mod.rs\n\nIn `src/plugins/mod.rs`, add your module:\n\n```rust\npub mod my_plugin;\n```\n\n### Step 8: Configure in YAML\n\nEnable your plugin in the router configuration:\n\n```yaml\nplugins:\n  acme.my_plugin:\n    enabled: true\n```\n\n## Common Patterns\n\nFor implementation patterns and code examples, see [references/service-hooks.md](references/service-hooks.md):\n- Enable/disable pattern\n- Request/response transformation (`map_request`, `map_response`)\n- Checkpoint (early return/short-circuit)\n- Context passing between hooks\n- Async operations (`checkpoint_async`, `buffered`)\n- Error response builders\n\n## Examples\n\n### Apollo Router Examples\n\nLocated in the [Apollo Router plugins directory](https://github.com/apollographql/router/tree/dev/apollo-router/src/plugins):\n\n| Plugin                 | Service Hook           | Pattern           | Description                 |\n|------------------------|------------------------|-------------------|-----------------------------|\n| `forbid_mutations.rs`  | `execution_service`    | checkpoint        | Simple gate on query plan   |\n| `expose_query_plan.rs` | execution + supergraph | Context passing   | Multi-service coordination  |\n| `cors.rs`              | `router_service`       | HTTP layer        | CORS handling at HTTP level |\n| `headers/`             | `subgraph_service`     | Layer composition | Complex header manipulation |\n\nFor full code examples and testing patterns, see [references/examples.md](references/examples.md).\n\n## Prerequisites\n\nIt is advised to have the [rust-best-practices](https://skills.sh/apollographql/skills/rust-best-practices) skill installed for writing idiomatic Rust code when developing router plugins. If installed, follow those best practices when generating or modifying plugin code.\n\n## Resources\n\n- [references/service-hooks.md](references/service-hooks.md) - Detailed service hook implementations\n- [references/existing-plugins.md](references/existing-plugins.md) - Index of existing plugins\n- [references/examples.md](references/examples.md) - Full code examples and testing patterns\n- Apollo Router plugins: https://github.com/apollographql/router/tree/dev/apollo-router/src/plugins","tags":["apollo","router","plugin","creator","skills","apollographql","agent-skills","graphql"],"capabilities":["skill","source-apollographql","skill-apollo-router-plugin-creator","topic-agent-skills","topic-apollo","topic-graphql"],"categories":["skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/apollographql/skills/apollo-router-plugin-creator","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add apollographql/skills","source_repo":"https://github.com/apollographql/skills","install_from":"skills.sh"}},"qualityScore":"0.726","qualityRationale":"deterministic score 0.73 from registry signals: · indexed on github topic:agent-skills · official publisher · 52 github stars · SKILL.md body (15,761 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T00:56:15.190Z","embedding":null,"createdAt":"2026-04-18T22:17:23.871Z","updatedAt":"2026-04-22T00:56:15.190Z","lastSeenAt":"2026-04-22T00:56:15.190Z","tsv":"'/apollographql/router/tree/dev/apollo-router/src/plugins':957 '/apollographql/router/tree/dev/apollo-router/src/plugins):':842 '/apollographql/skills/rust-best-practices)':907 '1':18,520 '2':27,573 '3':42,616 '4':628 '5':682 '6':739 '7':762 '8':778 'access':178 'acm':757 'acme.my':791 'add':31,218,284,432,609,668,683,763,769 'advis':897 'anonym':222 'apollo':2,9,51,60,538,544,549,830,836,952 'apollo-router-plugin-cr':1 'around':435 'assembl':112 'async':414,416,422,429,645,647,656,821,824 'authent':155 'base':259,671,692 'before/after':498 'begin':144,189 'best':903,923 'block':255 'bodi':181 'bool':608 'bottom':744 'box':737 'boxerror':563,663 'boxservic':341,343,350,352,359,361,370,372,714,716 'buffer':423,825 'builder':828 'call':296,304,319,501 'check':220 'checkpoint':405,413,814,823,851 'choos':450,676,686 'circuit':411,421 'client':64,122,299,315,507 'clone':426,598 'code':801,886,914,930,947 'common':795 'communic':267,279 'complex':881 'compos':380 'composit':880 'config':639,654 'configur':277,575,581,591,611,625,666,779,788 'const':566 'constructor':643 'context':171,817,860 'control':441,473 'controlflow':536 'convert':76 'coordin':865 'cor':871 'correspond':331 'cors.rs':866 'creat':22,55,521,524 'creator':5,54 'custom':165,202,243 'data':455 'debug':597,622 'decis':263 'default':599 'defin':574,617 'deriv':587,596,621 'descript':137,847 'deseri':560,584,600 'detail':703,934 'develop':916 'directori':839 'doesn':175 'durat':445 'dynam':283 'earli':815 'editor':594 'enabl':424,590,604,607,782,793 'enable/disable':806 'end':147,192 'error':826 'everi':577 'exampl':153,215,250,281,704,802,829,832,887,948 'execut':38,69,86,127,224,229,239,248,354,358,360,468,494,495,849,858 'exist':48,942 'expose_query_plan.rs':857 'field':612 'file':523,527,748 'final':504 'fn':335,344,353,362,391,399,406,415,657,708 'follow':921 'forbid_mutations.rs':848 'full':885,946 'gate':853 'generat':926 'generated.define':238 'github.com':841,956 'github.com/apollographql/router/tree/dev/apollo-router/src/plugins':955 'github.com/apollographql/router/tree/dev/apollo-router/src/plugins):':840 'govern':247 'graphql':195,208,212,462,479 'graphql/json':81,117 'guid':6 'handl':226,266,872 'header':173,286,458,876,882 'hook':33,133,374,382,386,453,670,679,685,691,706,820,845,936 'http':78,120,150,170,285,457,869,874 'idiomat':912 'impl':649 'implement':515,629,632,798,937 'import':531 'includ':244 'index':940 'indic':326 'individu':373 'init':659 'init.config':667 'initi':83,88,92,96,100,104,108,227 'instal':909,920 'instrument':430 'interact':168,205 'jsonschema':557,586,589,601 'jwt':154 'layer':376,870,879 'level':875 'lifecycl':63 'lifecycle.define':197 'lifecycle.for':152 'limit':438,449 'locat':833 'logic':245 'manipul':883 'map':389,397,723,729,810,812 'mod':774 'mod.rs':766 'modifi':46,928 'modul':764,771 'multi':863 'multi-servic':862 'myplugin':624,652,665,760 'mypluginconfig':603,626,655 'name':328,366,568 'nativ':11,56 'need':166,203,427,456,579,614,674 'new':24,526,642,658,722 'num':439 'ok':664 'op':535 'oper':91,95,99,103,107,111,447,822 'overview':135,698,701 'par':87 'paramet':324 'pars':480,485 'particular':257 'pass':288,321,818,861 'pattern':516,796,799,807,846,890,951 'per':298,306,471 'per-subgraph':470 'perform':157 'period':440 'plan':85,233,467,487,492,856 'plugi':50 'plugin':4,13,26,53,58,522,540,541,547,567,571,578,606,618,630,634,650,741,747,756,759,776,784,790,792,838,843,918,929,943,954 'plugininit':542,660 'polici':262 'practic':904,924 'prerequisit':894 'proceed':395 'properti':182 'pub':773 'purpos':387 'queri':84,223,232,258,466,855 'query/variables':463 'quick':517 'rate':437 'raw':77 'references/examples.md':892,893,944,945 'references/existing-plugins.md':938,939 'references/service-hooks.md':512,513,804,805,932,933 'regist':546,740,749,755 'req':725,728 'request':62,75,79,82,151,196,209,300,308,317,390,393,442,483,490,497,724,727,811 'request/response':808 'requir':311,530,638,695 'res':731,734 'resolv':313 'resourc':931 'respons':115,118,121,213,398,401,505,510,730,733,813,827 'result':661 'return':114,116,119,403,719 'return/short-circuit':816 'router':3,10,25,34,49,52,61,65,123,138,161,270,336,340,342,460,481,508,539,545,550,552,753,787,831,837,867,917,953 'routerservice.define':160 'run':140,185 'rust':12,57,334,532,595,620,644,707,754,772,902,913 'rust-best-practic':901 'schemar':556 'section':680 'see':511,675,696,803,891 'self':338,347,356,365,662,711 'self.configuration.enabled':718 'send':74 'serd':559 'servic':32,35,37,39,41,66,68,70,72,124,126,128,130,132,134,136,139,162,184,199,225,240,265,275,294,302,337,339,346,348,355,357,364,368,385,425,436,452,461,465,469,475,482,489,496,503,509,551,669,678,684,688,697,700,705,710,712,720,735,736,844,850,864,868,878,935 'service-overview':699 'servicebuild':378,564,721 'serviceext':565 'set':446 'short':410,420 'short-circuit':409,419 'signatur':333 'simpl':852 'skill':16,908 'skill-apollo-router-plugin-creator' 'skills.sh':906 'skills.sh/apollographql/skills/rust-best-practices)':905 'source-apollographql' 'span':431,434 'src/plugins/mod.rs':768 'src/plugins/my_plugin.rs':528 'start':518 'std':534 'step':519,572,615,627,681,738,761,777 'str':367,569 'struct':576,582,602,619,623 'sub':90,94,98,102,106,110 'sub-oper':89,93,97,101,105,109 'subgraph':40,71,129,264,274,291,307,323,332,363,369,371,472,474,500,502,553,877 'subgraphs.define':273 'supergraph':36,67,125,183,198,345,349,351,464,488,554,709,713,715,859 'support':177 'sync':396,404,412 'sync/async':388 'test':889,950 'throughput':443 'time':448,477 'timeout':444 'topic-agent-skills' 'topic-apollo' 'topic-graphql' 'tower':375,562 'trace':433 'trait':631,635,646,648 'transform':392,400,726,732,809 'true':794 'type':640,653 'use':14,377,533,537,543,548,555,558,561 'user':19,28,43 'valid':417,592 'validate/filter':407 'want':20,29,44,253 'wherea':292 'within':158,383 'write':8,911 'yaml':781,789","prices":[{"id":"7bf1bc96-7ea6-42eb-aa64-3099a82b9df6","listingId":"0e1d1786-959b-451e-a473-15170ac0bb42","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"apollographql","category":"skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:17:23.871Z"}],"sources":[{"listingId":"0e1d1786-959b-451e-a473-15170ac0bb42","source":"github","sourceId":"apollographql/skills/apollo-router-plugin-creator","sourceUrl":"https://github.com/apollographql/skills/tree/main/skills/apollo-router-plugin-creator","isPrimary":false,"firstSeenAt":"2026-04-18T22:17:23.871Z","lastSeenAt":"2026-04-22T00:56:15.190Z"}],"details":{"listingId":"0e1d1786-959b-451e-a473-15170ac0bb42","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"apollographql","slug":"apollo-router-plugin-creator","github":{"repo":"apollographql/skills","stars":52,"topics":["agent-skills","apollo","graphql"],"license":"mit","html_url":"https://github.com/apollographql/skills","pushed_at":"2026-04-16T16:01:23Z","description":"Apollo GraphQL Agent Skills","skill_md_sha":"cf338602b17b45fd2cbd25eaa382c013054ebbca","skill_md_path":"skills/apollo-router-plugin-creator/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/apollographql/skills/tree/main/skills/apollo-router-plugin-creator"},"layout":"multi","source":"github","category":"skills","frontmatter":{"name":"apollo-router-plugin-creator","license":"MIT","description":"Guide for writing Apollo Router native Rust plugins. Use this skill when: (1) users want to create a new router plugin, (2) users want to add service hooks (router_service, supergraph_service, execution_service, subgraph_service), (3) users want to modify an existing router plugin, (4) users need to understand router plugin patterns or the request lifecycle. (5) triggers on requests like \"create a new plugin\", \"add a router plugin\", \"modify the X plugin\", or \"add subgraph_service hook\"."},"skills_sh_url":"https://skills.sh/apollographql/skills/apollo-router-plugin-creator"},"updatedAt":"2026-04-22T00:56:15.190Z"}}