Yak Docs
Tool Adapters

GraphQL Adapter

Provide your GraphQL schema to Yak, and the AI generates appropriate queries. You handle execution against your GraphQL endpoint.

How It Works

  1. You provide your GraphQL schema
  2. Yak injects it as context to the LLM
  3. The AI generates queries based on user requests
  4. Your handler executes the queries and returns results

Setup

import { YakProvider, YakWidget } from "@yak-io/nextjs/client";

const graphqlSchema = `
  type User {
    id: ID!
    name: String!
    email: String!
    orders: [Order!]!
  }
  
  type Order {
    id: ID!
    total: Float!
    status: String!
  }
  
  type Query {
    user(id: ID!): User
    users(limit: Int): [User!]!
    order(id: ID!): Order
  }
  
  type Mutation {
    updateOrderStatus(id: ID!, status: String!): Order
  }
`;

export default function App() {
  return (
    <YakProvider
      appId="your-app-id"
      getConfig={async () => ({
        schemaSources: [
          {
            name: "myApi",
            type: "graphql",
            schema: graphqlSchema,
          },
        ],
      })}
      onGraphQLSchemaCall={async (schemaName, request) => {
        // schemaName = "myApi"
        // request = { query: "...", variables: {...} }
        const res = await fetch("https://api.example.com/graphql", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${token}`,
          },
          body: JSON.stringify({
            query: request.query,
            variables: request.variables,
          }),
        });
        const { data, errors } = await res.json();
        if (errors) throw new Error(errors[0].message);
        return data;
      }}
    >
      <YakWidget />
    </YakProvider>
  );
}

Multiple Schemas

Route calls to different endpoints by schema name:

<YakProvider
  getConfig={async () => ({
    schemaSources: [
      { name: "users", type: "graphql", schema: usersSchema },
      { name: "inventory", type: "graphql", schema: inventorySchema },
    ],
  })}
  onGraphQLSchemaCall={async (schemaName, request) => {
    const endpoints = {
      users: "https://users.api.example.com/graphql",
      inventory: "https://inventory.api.example.com/graphql",
    };
    const endpoint = endpoints[schemaName];
    
    const res = await fetch(endpoint, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(request),
    });
    return res.json();
  }}
/>

Best Practices

Keep Schemas Focused

Provide only the relevant parts of your schema:

// Instead of your entire schema, extract relevant portions
const relevantSchema = `
  type Order {
    id: ID!
    total: Float!
    status: String!
  }
  
  type Query {
    orders(limit: Int, status: String): [Order!]!
    order(id: ID!): Order
  }
`;

Use Descriptive Names

// Good - clear what each schema is for
{ name: "userService", type: "graphql", schema: userSchema }
{ name: "orderManagement", type: "graphql", schema: orderSchema }

// Avoid - too generic
{ name: "api1", type: "graphql", schema: schema }

Handle Errors

Return meaningful error messages:

onGraphQLSchemaCall: async (schemaName, request) => {
  try {
    const result = await executeGraphQL(request);
    return result;
  } catch (error) {
    if (error instanceof AuthError) {
      return { error: "Not authorized to access this data" };
    }
    throw error;
  }
}

Add Authentication

Always authenticate requests:

onGraphQLSchemaCall: async (schemaName, request) => {
  const res = await fetch(endpoint, {
    headers: {
      Authorization: `Bearer ${getAuthToken()}`,
    },
    // ...
  });
}

Be careful about which operations you expose. Avoid including mutations that could be destructive without proper authorization checks.

On this page