Agent-skills api-graphql-grpc
install
source · Clone the upstream repo
git clone https://github.com/LambdaTest/agent-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/LambdaTest/agent-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/api/graphql-grpc-helper" ~/.claude/skills/lambdatest-agent-skills-api-graphql-grpc && rm -rf "$T"
manifest:
api/graphql-grpc-helper/SKILL.mdsource content
GraphQL & gRPC Skill
Design schemas, resolvers, and service definitions for GraphQL and gRPC APIs.
GraphQL Schema Design
# Scalars scalar DateTime scalar UUID scalar JSON # Enums enum OrderStatus { PENDING PAID SHIPPED DELIVERED CANCELLED } enum UserRole { ADMIN EDITOR VIEWER } # Types type User { id: UUID! name: String! email: String! role: UserRole! orders(first: Int, after: String): OrderConnection! createdAt: DateTime! } type Order { id: UUID! status: OrderStatus! total: Float! items: [OrderItem!]! user: User! createdAt: DateTime! } type OrderItem { id: UUID! product: Product! quantity: Int! price: Float! } # Pagination (Relay cursor spec) type OrderConnection { edges: [OrderEdge!]! pageInfo: PageInfo! totalCount: Int! } type OrderEdge { node: Order!; cursor: String! } type PageInfo { hasNextPage: Boolean! hasPreviousPage: Boolean! startCursor: String endCursor: String } # Queries type Query { me: User user(id: UUID!): User users(first: Int, after: String, role: UserRole): UserConnection! order(id: UUID!): Order orders(status: OrderStatus, first: Int, after: String): OrderConnection! } # Mutations type Mutation { createUser(input: CreateUserInput!): CreateUserPayload! updateUser(id: UUID!, input: UpdateUserInput!): UpdateUserPayload! deleteUser(id: UUID!): DeletePayload! createOrder(input: CreateOrderInput!): CreateOrderPayload! cancelOrder(id: UUID!): CancelOrderPayload! } # Subscriptions type Subscription { orderStatusChanged(orderId: UUID!): Order! newOrder: Order! } # Inputs & Payloads input CreateUserInput { name: String!; email: String!; role: UserRole } type CreateUserPayload { user: User; errors: [UserError!] } type UserError { field: String; message: String! }
Resolver Pattern (DataLoader — solves N+1)
// Without DataLoader: N+1 queries // With DataLoader: batch all user IDs into one SQL IN(...) const userLoader = new DataLoader(async (userIds) => { const users = await db.query(`SELECT * FROM users WHERE id = ANY($1)`, [userIds]); // Return in same order as input IDs return userIds.map(id => users.find(u => u.id === id) || null); }); const resolvers = { Order: { user: (order, _, { loaders }) => loaders.user.load(order.userId), }, Query: { orders: async (_, { status, first = 20, after }) => { return paginatedQuery('orders', { status, first, after }); } } };
Error Handling in GraphQL
{ "data": { "createUser": null }, "errors": [ { "message": "Email already in use", "locations": [{ "line": 2, "column": 3 }], "path": ["createUser"], "extensions": { "code": "USER_EMAIL_TAKEN", "field": "email" } } ] }
gRPC Proto Definition
syntax = "proto3"; package users.v1; option go_package = "github.com/example/api/users/v1"; import "google/protobuf/timestamp.proto"; import "google/protobuf/empty.proto"; service UsersService { // Unary RPCs rpc GetUser(GetUserRequest) returns (User); rpc CreateUser(CreateUserRequest) returns (User); rpc UpdateUser(UpdateUserRequest) returns (User); rpc DeleteUser(DeleteUserRequest) returns (google.protobuf.Empty); rpc ListUsers(ListUsersRequest) returns (ListUsersResponse); // Server streaming rpc WatchUser(GetUserRequest) returns (stream User); // Bidirectional streaming rpc SyncUsers(stream SyncRequest) returns (stream SyncResponse); } message User { string id = 1; string name = 2; string email = 3; string role = 4; google.protobuf.Timestamp created_at = 5; } message GetUserRequest { string id = 1; } message CreateUserRequest { string name = 1; string email = 2; string role = 3; } message UpdateUserRequest { string id = 1; string name = 2; string email = 3; } message DeleteUserRequest { string id = 1; } message ListUsersRequest { int32 page = 1; int32 limit = 2; string role = 3; } message ListUsersResponse { repeated User users = 1; int32 total = 2; }
REST vs GraphQL vs gRPC Decision Matrix
| Factor | REST | GraphQL | gRPC |
|---|---|---|---|
| Public API | ✓ Best | ✓ Good | ✗ |
| Mobile clients (bandwidth) | ✗ Over-fetch | ✓ Best | ✓ |
| Microservices (internal) | ✓ | ✗ | ✓ Best |
| Streaming / real-time | ✗ | ✓ Subscriptions | ✓ Best |
| Complex queries | ✗ N endpoints | ✓ Best | ✗ |
| Caching | ✓ HTTP cache | ✗ Complex | ✗ |
| Browser native | ✓ | ✓ | ✗ (needs proxy) |
After Completing the API Design
Once the graphql/grpc design output is delivered, ask the user:
"Would you like me to generate API documentation for this design? (yes/no)"
If the user says yes:
- Check if the API Documentation skill is available in the installed skills list
- If the skill is available:
- Read and follow the instructions in the API Documentation skill
- Use the API design output above as the input
- If the skill is NOT available:
- Inform the user: "It looks like the API Documentation skill isn't installed. You can install it and re-run.
If the user says no:
- End the task here