Consolidate GitLab API tools into generic gitlab_api_get and gitlab_graphql tools
Problem Statement
Currently, Duo Workflow Chat exposes numerous specialized tools for interacting with GitLab resources, including:
-
get_merge_request,list_merge_request_diffs,list_all_merge_request_notes,gitlab_merge_request_search -
get_issue,list_issues,list_issue_notes,get_issue_note get_project- Similar patterns for commits, pipelines, jobs, epics, work items, vulnerabilities, security findings, audit events, etc.
This approach has several limitations:
- High token consumption: Each specialized tool adds to the token count in the system prompt, reducing available context for actual work
- Limited functionality: We can only expose GitLab API endpoints that have been explicitly implemented as tools
- Maintenance overhead: Every new GitLab API feature requires implementing and maintaining a new tool class
- Inconsistent coverage: Some resources have comprehensive tooling while others have gaps
Proposed Solution
Replace specialized read-only Get* and List* tools with two generic tools:
1. gitlab_api_get
A generic REST API tool for read operations only that accepts:
-
endpoint: The API path (e.g.,/api/v4/projects/:id/merge_requests/:iid) -
params: Optional query parameters as a dictionary - URL parsing support to extract resource IDs from GitLab URLs
Security constraint: Only supports GET requests. All write operations (POST, PUT, DELETE) remain as specialized tools with proper validation.
2. gitlab_graphql
A generic GraphQL tool that accepts:
-
query: The GraphQL query string (queries only, no mutations) -
variables: Optional variables dictionary
Security constraint: Only supports GraphQL queries, not mutations. Write operations remain as specialized tools.
Benefits
- Reduced token usage: Two generic read tools instead of 50+ specialized tools significantly reduces system prompt size
- Complete read API access: LLM can access any GitLab REST or GraphQL read endpoint, not just pre-implemented ones
- Simplified maintenance: No need to implement wrapper tools for every read-only API endpoint
- Future-proof: New GitLab API features automatically available without code changes
- More flexible: LLM can construct custom queries for complex data requirements
Implementation Considerations
Preserve these specialized tools:
- All write operations:
create_merge_request,create_issue,update_merge_request,create_merge_request_note, etc. (these require validation, business logic, and approval workflows) - Custom tools with complex processing:
list_merge_request_diffs(appliesDiffExclusionPolicy),build_review_merge_request_context, etc. - Tools that bundle multiple operations or have special behavior
Replace these with generic tools:
-
get_merge_request→gitlab_api_get -
list_issues→gitlab_api_get -
get_project→gitlab_api_get -
list_all_merge_request_notes→gitlab_api_get -
get_issue_note→gitlab_api_get - Similar patterns for commits, pipelines, jobs, epics, work items, vulnerabilities, security findings, audit events, users, etc.
URL parsing:
- Generic tools should support the same URL parsing capabilities that specialized tools currently have (extracting project_id, merge_request_iid, issue_iid, etc. from GitLab URLs)
- Example:
gitlab_api_get(url="https://gitlab.com/namespace/project/-/merge_requests/42")should work equivalently togitlab_api_get(endpoint="/api/v4/projects/namespace%2Fproject/merge_requests/42")
Documentation:
- System prompt should include examples of common API patterns
- Inline documentation for frequently-used endpoints (projects, merge requests, issues, pipelines)
- Reference to GitLab API documentation
Error handling:
- Generic tools should provide clear error messages including status codes and response bodies
- Maintain consistency with current error handling patterns
Example Usage
Current approach:
# Requires 3 separate specialized tools in system prompt
get_merge_request(project_id=13, merge_request_iid=42)
list_all_merge_request_notes(project_id=13, merge_request_iid=42)
get_issue(project_id=13, issue_iid=10)
New approach:
# Single generic tool can handle all GET requests
gitlab_api_get(endpoint="/api/v4/projects/13/merge_requests/42")
gitlab_api_get(endpoint="/api/v4/projects/13/merge_requests/42/notes")
gitlab_api_get(endpoint="/api/v4/projects/13/issues/10")
# Or with URL parsing
gitlab_api_get(url="https://gitlab.com/namespace/project/-/merge_requests/42")
# With query parameters
gitlab_api_get(
endpoint="/api/v4/projects/13/merge_requests",
params={"state": "opened", "author_username": "janedoe"}
)
# GraphQL for complex queries combining multiple resources
gitlab_graphql(query="""
query($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
mergeRequest(iid: $iid) {
title
description
author { username }
diffStats { additions deletions }
notes { nodes { body author { username } } }
}
}
}
""", variables={"projectPath": "namespace/project", "iid": "42"})
Security Notes
- Generic tools are read-only by design - no POST, PUT, PATCH, or DELETE support
- GraphQL tool only accepts queries, not mutations
- All write operations require explicit specialized tools with proper validation and approval workflows
- This maintains security boundaries while maximizing flexibility for read operations
Edited by 🤖 GitLab Bot 🤖