Don't Let AI Agents Improvise Against Production GraphQL

cover
Ahmet Soormally

Ahmet Soormally

Principal Solutions Engineer at WunderGraph

min read

TL;DR

AI agents should never improvise against your production GraphQL graph. Use an open-world setup in development (full schema + arbitrary operations) so agents can discover useful queries, then lock production down to a safelist of named, reviewed persisted operations exposed as tools through the Cosmo Router MCP Gateway.

The fastest way to prototype an AI agent is also the worst way to ship one: give it your whole GraphQL schema and let it run arbitrary operations.

In development, that feels magical. The agent introspects the graph, writes queries, fixes its own mistakes, and returns useful data in minutes.

In production, the same setup is a governance problem. The agent can discover fields you never meant to expose, compose operations no one reviewed, and reach across every subgraph your federation connects. Handing an autonomous agent arbitrary, unaudited execution over your entire graph is exactly what no one wants to be responsible for.

And most teams are about to make it worse. The instinct is to recreate, for agents, the same API sprawl we spent the last decade untangling: shadow MCP (Model Context Protocol) servers standing up next to every service, invisible to the gateway; bespoke "AI-safe" APIs forked off the real one and left to drift; unreviewed tool surfaces wired straight to production; agents carrying standing privileges no one audits. Call it shadow MCP sprawl. We adopted federation to kill fragmentation. Pointing agents at the graph through a dozen ungoverned side doors throws that win away before anyone notices.

The answer is not a second "AI-safe" API. That is just another surface to maintain, and your AI-safe REST API is probably tomorrow's legacy system. The answer is one rule you can repeat in a review: let agents discover in development, but only let them execute reviewed operations in production.

The anti-pattern: production agents with open-ended API access

The wrong way to connect an AI agent to GraphQL is to give it a GraphQL client. In development, that is exactly right. In production, it is reckless.

Open-ended access means two capabilities: the agent can read your whole schema and run any query or mutation it composes. Against a federated graph that is reaching into every field, every subgraph contributes. And it does not matter that the traffic runs through your sanctioned gateway. An agent in this posture is indistinguishable from the shadow MCP server you were worried about. A gateway is only a governance win if it does not ship in open-world mode.

Production agents should not write queries. They should invoke reviewed operations.

The principle: agents should invoke capabilities, not invent them

A capability is a named, reviewed thing your system already knows how to do: GetCustomerOrders, SearchTickets, CreateRefundDraft. Inventing is what arbitrary execution allows: the agent composes an operation at runtime that no human ever saw.

The distinction matters because review is what makes an operation safe, and you cannot review what does not exist yet. An invented query has no audit trail, no scope policy, no field-level sign-off, and no test. A named operation has all four. So the move from dev to prod is not "trust the agent more." It is "turn discovered behavior into reviewed software."

The pattern: design in an open world, ship in a closed world

The pattern is one sentence: design in an open world, ship in a closed one. Operationally, let agents discover in development, but only let them execute reviewed operations in production.

Open world
full schema + arbitrary GraphQL
Reviewed operations
named .graphql files
Closed world
safelisted tools only

The same server runs both ends. The Cosmo Router MCP Gateway exposes your GraphQL supergraph over the Model Context Protocol , and a configuration flag decides how much of it an agent can reach. This is the practical side of an argument we have made before: MCP is the coordination layer, and a federated GraphQL graph is the governed data layer underneath it.

Development: open world

In development, the agent gets schema visibility and arbitrary execution. The purpose is exploration, prototyping, and operational discovery.

1
2
3
4

Connected through Cursor or Claude, the agent introspects your federated types and drafts queries against real data until one does the job:

1
2
3
4
5
6
7
8
9
10
11

This is allowed because development is where the agent is supposed to discover the shape of the graph.

The promotion boundary: discovered behavior becomes reviewed software

Once you know which behavior is useful, you save it as a named .graphql operation. It now goes through ordinary engineering review:

  • Does it expose the right fields, and no PII you did not intend?
  • Does it need authorization, and which scopes?
  • Is it safe to run repeatedly?
  • Should it be query-only, mutation-capable, or gated behind human approval?

This is the key move. The transition from dev to prod is not the agent earning more trust. It is discovered behavior becoming a reviewed software artifact: a persisted operation, a trusted document that now lives in your codebase like any other reviewed code.

Production: closed world

In production, disable introspection and arbitrary execution. The agent sees only your approved operations as tools.

1
2
3
4
5
6

The agent no longer has "GraphQL access." It has a finite tool surface. Same router, same schema, same agent. The only thing that changed is the posture.

Before, in the open world, the agent's tools were:

1
2

After, in the closed world, they are:

1
2
3

Its entire capability surface went from "your whole graph" to three named, reviewed actions, one per .graphql file in the directory. That is the model, in one before-and-after.

Rules for production agent access

The pattern only holds if you are disciplined about what you promote. These are the rules worth writing down.

Rule 1: No arbitrary GraphQL execution in production. If an operation matters, name it, review it, safelist it, and expose it as a tool. Arbitrary execution is a development tool, not a production one.

Rule 2: Agents do not get schemas by default. Schema visibility is a deliberate posture, not an incidental convenience. Turn it on in production only when you have decided agents should reason about the surface, and never as a side effect.

Rule 3: Mutations require a higher bar than queries. A production mutation exposed to an agent should usually be a draft, a validation, a request, or a create-with-approval:

1
2
3

Avoid exposing direct destructive tools unless they carry strong authorization, full auditability, and usually a human in the loop:

1
2
3
4

Rule 4: Tool names are part of the security model. Do not expose generic tools like execute_graphql, runQuery, or callBackend. Prefer intention-revealing operations whose names tell a reviewer and the agent exactly what they do: GetCustomerOrderHistory, CreateRefundDraft, SearchSupportTickets, CheckInvoiceStatus. The operation name becomes the tool name, so naming is governance.

Rule 5: The safelist is the agent contract. Your .graphql operations are not implementation details. They are the production interface between agents and the graph. Treat changes to them like changes to a public API.

What a safelist does not solve

A safelist is not a force field. It does not make an agent trustworthy; it makes the agent's failures bounded.

An agent can still call a permitted operation with bad arguments, chain permitted operations toward an outcome you did not intend, or surface permitted data into a context it should not. What the closed world guarantees is that the set of things that can go wrong is the set of operations you reviewed, not the entire graph. That is a smaller, knowable surface, and a knowable surface is the precondition for every other control: rate limits, per-operation scopes, human-approval gates on sensitive mutations, anomaly detection on the audit trail.

Treat the safelist as the floor of your agent security model, not the ceiling. Prompt injection, hallucinated tool use, token and cost budgets, and data-retention policy all live above this layer and still need their own controls. The closed world is what makes those controls tractable, because they apply to a few dozen named operations instead of an open-ended query surface.

The takeaway

Let agents discover in development, but only let them execute reviewed operations in production.

That is the whole pattern. The same gateway gives you both ends, so you are not standing up infrastructure to make your graph safe for AI; you are switching a posture on infrastructure you already run. Three shapes it takes in practice:

  • Platform team — governance across the org. The platform team owns the operations directory and the access policy. Product teams contribute operations through review, and every connected agent gets a consistent, audited surface that schema changes never quietly expand.
  • Security and AI enablement — a support assistant over sensitive data. Expose a handful of operations like GetCustomerOrders, each documented to exclude payment instruments and internal codes. The artifact a reviewer signs off on is a small directory of operations, not an entire API surface, and every call is attributable to the agent that made it.
  • AI agent engineer — from prototype to production. Run wide open in a dev namespace, let the agent discover the operations that earn their place, then promote that directory to a locked-down production gateway. You reach a production-grade agent without building the safety scaffolding from scratch, because the exploration produces the very artifact production consumes.

Frequently Asked Questions (FAQ)

No. Arbitrary execution (an execute_graphql-style tool plus full schema introspection) is the right setup in development, where the agent is meant to explore and discover useful operations. In production, it is reckless: the agent can reach any field any subgraph exposes and compose operations no one reviewed. Production agents should invoke reviewed, named operations, not write queries at runtime.

Running GraphQL means the agent composes operations at runtime that no human reviewed. A safelist means the agent can only invoke a fixed set of pre-approved operations, each exposed as its own tool. Review is what makes an operation safe, and you cannot review what does not exist yet, so the safelist is what turns discovered behavior into reviewed software before it reaches production.

No. A safelist does not make an agent trustworthy; it makes the agent's failures bounded. The agent can still call a permitted operation with bad arguments or chain permitted operations toward an unintended outcome. What the safelist guarantees is that the set of things that can go wrong is the set of operations you reviewed, not your entire graph. That bounded surface is the precondition for rate limits, scopes, human-approval gates, and anomaly detection.

Give every agent one trusted place to connect. Without a central gateway, any developer can stand up their own MCP server against an internal API and wire an agent to it, bypassing your gateway and WAF, with no inventory of which agents reach which systems. A governed gateway with arbitrary execution and schema introspection off by default, and least-privilege scopes per operation, drives that shadow surface toward zero.

The Cosmo Router MCP Gateway exposes your GraphQL supergraph as tools over the Model Context Protocol. It loads operations from a directory, validates them against your schema, and generates an execute_operation_<name> tool for each one. Two optional flags extend this: expose_schema adds a get_schema tool for full schema introspection, and enable_arbitrary_operations adds an execute_graphql tool for ad-hoc queries — disable both in production to limit agents to your approved operations.


Ahmet Soormally
Ahmet Soormally

Principal Solutions Engineer at WunderGraph

Ahmet is a Principal Solutions Engineer at WunderGraph, helping teams adopt Cosmo. He leads technical evaluations, builds prototypes, and runs workshops to accelerate adoption, while improving SDKs, documentation, and onboarding to enhance the developer experience.