From arize-toolkit-dev
Guides adding new GraphQL queries/mutations to Arize Toolkit via phased workflow: schema exploration, models/types generation, tests, client methods, docs. For arize_toolkit API extensions.
How this skill is triggered — by the user, by Claude, or both
Slash command
/arize-toolkit-dev:new-query-workflowThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Complete workflow for adding GraphQL queries/mutations to the Arize Toolkit with all supporting components.
Complete workflow for adding GraphQL queries/mutations to the Arize Toolkit with all supporting components.
Phase 1: GraphQL Development → Phase 2: Component Discovery → Phase 3: Gap Analysis
↓
Phase 7: Documentation ← Phase 6: CLI ← Phase 5: Testing ← Phase 4: Implementation
Execute phases in order. Pause for user validation after Phases 1, 3, and 4.
Goal: Develop and validate the GraphQL query using the arize-graphql-analytics skill.
Pause: Present query specification to user for validation before proceeding.
Goal: Identify all components needed and their locations.
From the GraphQL analysis, catalog:
arize_toolkit/types.py)arize_toolkit/models/)arize_toolkit/models/)| Domain | Query File | Model File |
|---|---|---|
| Models/Datasets | model_queries.py | base_models.py |
| Monitors/Alerts | monitor_queries.py | monitor_models.py |
| Dashboards | dashboard_queries.py | dashboard_models.py |
| LLM/Prompts | llm_utils_queries.py | llm_utils_models.py |
| Data Import | data_import_queries.py | data_import_models.py |
| Spaces/Orgs | space_queries.py | space_models.py |
| Custom Metrics | custom_metric_queries.py | custom_metrics_models.py |
Check if the new functionality depends on existing queries (e.g., need model ID before creating monitor).
Goal: Identify what needs to be created vs. reused.
For each enum in the query not in types.py:
For each input/response type not in models/:
GraphQLModel, BaseNode, etc.)Determine:
get_, get_all_, create_, update_, delete_, copy_Pause: Present gap analysis to user. Confirm implementation plan.
Execute in order to manage dependencies. See references/implementation-patterns.md for detailed patterns.
File: arize_toolkit/types.py
class NewEnumType(InputValidationEnum):
"""Description. Values verified from GraphQL schema."""
value_one = "apiValue", "User Friendly", "alias"
File: arize_toolkit/models/{domain}_models.py
class NewModel(GraphQLModel):
id: str = Field(description="Unique identifier")
name: str = Field(description="Name")
optional_field: Optional[str] = Field(default=None, description="Optional")
File: arize_toolkit/queries/{domain}_queries.py
class NewOperationQuery(BaseQuery):
graphql_query: str = """..."""
query_description: str = "What this does"
class Variables(BaseVariables):
param: str
class QueryException(ArizeAPIException):
message: str = "Error message"
class QueryResponse(NewModel):
pass
@classmethod
def _parse_graphql_result(cls, result):
# Parse and return (results, has_next, cursor)
File: arize_toolkit/client.py
def get_new_resource(self, name: str) -> dict:
"""Retrieves resource by name.
Args:
name (str): Resource name
Returns:
dict: Resource data with id, name, etc.
Raises:
ValueError: If name is empty
ArizeAPIException: If not found
"""
result = NewOperationQuery.run_graphql_query(
self._graphql_client, space_id=self.space_id, name=name
)
return result.to_dict()
Pause: Present generated code for validation before adding tests.
See references/test-patterns.md for detailed patterns.
File: tests/test_types.py
Test enum values, aliases, and invalid input handling.
File: tests/test_models/test_{domain}_models.py
Test initialization, defaults, validation, and serialization.
File: tests/test_queries/test_{domain}_queries.py
Test query structure, success cases, error handling, and pagination.
File: tests/test_client.py
Test client methods with mocked GraphQL responses.
Goal: Expose the new client methods as CLI commands so they are accessible via arize_toolkit.
Match the domain to an existing command group file, or create a new one if needed:
| Domain | CLI File | Command Group |
|---|---|---|
| Models/Datasets | arize_toolkit/cli/models.py | models / projects |
| Monitors/Alerts | arize_toolkit/cli/monitors.py | monitors |
| Dashboards | arize_toolkit/cli/dashboards.py | dashboards |
| LLM/Prompts | arize_toolkit/cli/prompts.py | prompts |
| Data Import | arize_toolkit/cli/imports.py | imports |
| Spaces/Orgs | arize_toolkit/cli/spaces.py / arize_toolkit/cli/orgs.py | spaces / orgs |
| Custom Metrics | arize_toolkit/cli/custom_metrics.py | custom-metrics |
| Evaluators | arize_toolkit/cli/evaluators.py | evaluators |
Follow the existing Click command pattern in the target file:
@{group}.command("{verb}")
@click.argument("name") # positional args for required identifiers
@click.option("--model", required=True, help="Model name.") # named options
@click.option("--optional-flag", default=None, help="Description.")
@click.pass_context
def {group}_{verb}(ctx, name, model, optional_flag):
"""Help text shown in --help."""
client = get_client(ctx)
data = client.{client_method}(name=name, model_name=model, ...)
print_result(data, columns=[...], title="Title", json_mode=ctx.obj["json_mode"])
Key patterns:
@click.argument for required positional identifiers (resource name, ID)@click.option("--name", required=True) for required named parameters@click.option with default=None for optional parametersdelete) should add @click.option("--yes", is_flag=True) and call click.confirm() unless --yes is setprint_result() for data output, print_success() for confirmations, print_url() for linksget_client from arize_toolkit.cli.client_factoryarize_toolkit.cli.outputIf creating a new command group file, register it in arize_toolkit/cli/main.py:
from arize_toolkit.cli.{new_module} import {new}_group
cli.add_command({new}_group)
File: tests/test_cli/test_commands.py
Add tests following the existing pattern with mocked client:
class TestNewGroup:
def test_{group}_list(self, runner, mock_client):
mock_client.get_all_{resources}.return_value = [
{"id": "r1", "name": "resource1", "createdAt": "2025-01-01"},
]
result = runner.invoke(cli, ["{group}", "list"])
assert result.exit_code == 0
mock_client.get_all_{resources}.assert_called_once()
def test_{group}_get(self, runner, mock_client):
mock_client.get_{resource}.return_value = {"id": "r1", "name": "myresource"}
result = runner.invoke(cli, ["{group}", "get", "myresource"])
assert result.exit_code == 0
mock_client.get_{resource}.assert_called_once_with(name="myresource")
Also update the patch_get_client fixture's module list if adding a new CLI file.
File: .claude/skills/arize-cli/references/COMMANDS.md
Add the new commands to the appropriate section following the existing format.
See references/doc-patterns.md for detailed patterns.
File: docs_site/docs/{domain}_tools.md
Add method documentation with signature, parameters, returns, and example.
Add entry to the Overview table at top of documentation file.
docs_site/docs/index.mdmkdocs.yml under 'Tools'Before completing, verify:
Types: [ ] Defined in types.py [ ] Schema-verified values [ ] Aliases provided [ ] Tests added
Models: [ ] In correct models/ file [ ] Correct base class [ ] Field descriptions [ ] Tests added
Queries: [ ] In correct queries/ file [ ] Variables class complete [ ] Exception defined [ ] Response uses model [ ] Parser handles all cases [ ] Tests added
Client: [ ] CRUD naming convention [ ] Docstring complete [ ] Validation implemented [ ] Tests added
CLI: [ ] Commands added to correct group [ ] Arguments/options match client method params [ ] Output uses print_result/print_success [ ] CLI tests added [ ] patch_get_client fixture updated (if new file) [ ] arize-cli skill COMMANDS.md updated
Docs: [ ] Tool page updated [ ] Overview table updated [ ] Examples provided
npx claudepluginhub duncankmckinnon/arize_toolkit --plugin arize-toolkit-devQueries and analyzes Arize ML observability data via GraphQL using curl. Fetches schema, builds, executes, and debugs queries/mutations for spaces, models, monitors, datasets.
Builds production-ready GraphQL servers with schema design, DataLoader resolvers, WebSocket subscriptions, and field-level authorization for Node.js and Python.
Guides writing GraphQL operations (queries, mutations, subscriptions, fragments) with best practices for naming, variables, directives, and data fetching patterns.