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
- You provide your GraphQL schema
- Yak injects it as context to the LLM
- The AI generates queries based on user requests
- 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.