Python API for SkillSpector: Architecture, Components, and Usage Guide

The Python API for SkillSpector exposes a minimal, well-defined interface consisting of create_graph(), graph, InputHandler, and SkillspectorState for programmatic execution of LangGraph-based skill analysis workflows.

SkillSpector is an open-source Python package developed by NVIDIA for automated skill analysis. The Python API for SkillSpector enables developers to embed comprehensive skill scanning capabilities directly into applications without using the command-line interface. Through a small set of public symbols exposed in the top-level skillspector package, users can programmatically invoke the complete analysis pipeline, from input resolution to SARIF report generation.

Core Components of the Python API for SkillSpector

The public API surface is intentionally small to maximize ease of use while exposing the full power of the underlying LangGraph workflow.

Graph Factory and Pre-compiled Instance

The primary entry points reside in src/skillspector/__init__.py and src/skillspector/graph.py:

  • create_graph() – A factory function that returns a freshly compiled LangGraph workflow. According to the source code in src/skillspector/graph.py, this function wires together all SkillSpector nodes including input resolution, context building, static analyzers, LLM-driven analyzers, meta-analysis, and reporting.

  • graph – A ready-to-run singleton instance of the compiled workflow. This pre-compiled graph can be invoked directly with a state dictionary, making it ideal for reuse across multiple analysis operations.

Input Normalization

The InputHandler class, defined in src/skillspector/input_handler.py, serves as the primary utility for input sanitization. It normalizes any supported input format—including Git URLs, raw file URLs, zip archives, markdown files, or local directories—into a local directory path. When processing remote resources, it optionally creates a temporary directory for automatic cleanup.

State Management

SkillspectorState is a TypedDict defined in src/skillspector/state.py that describes the schema shared by all nodes in the workflow. This dictionary defines the keys that can be passed to graph.invoke() and specifies the values that nodes read and write during execution. It serves as the contract between the user and the analysis pipeline.

Workflow Execution Architecture

Understanding the Python API for SkillSpector requires familiarity with how the LangGraph workflow processes data through its nodes.

Graph Topology

The create_graph() function builds a StateGraph with the following topology, as defined in src/skillspector/graph.py (lines 45-51):


START → resolve_input → build_context → (each analyzer) → meta_analyzer → report → END

Each analyzer node registers its own ID in skillspector.nodes.analyzers.ANALYZER_NODE_IDS. The edges connect these nodes to form a complete analysis pipeline.

State Flow Through Nodes

The workflow passes a single SkillspectorState dictionary between nodes:

  1. resolve_input (src/skillspector/nodes/resolve_input.py) uses InputHandler to transform the user-supplied input_path into a local skill_path, adding an optional temp_dir_for_cleanup when temporary directories are created.

  2. build_context (src/skillspector/nodes/build_context.py) scans the directory, builds component lists, caches file contents and ASTs, and stores a comprehensive manifest in the state.

  3. Analyzer nodes (src/skillspector/nodes/analyzers/) read the manifest and augment state["findings"]. These nodes respect state["use_llm"] and retrieve LLM models via the provider protocols.

  4. meta_analyzer (src/skillspector/nodes/meta_analyzer.py) aggregates and filters findings, computes a risk score, and writes a SARIF or textual report structure.

  5. report (src/skillspector/nodes/report.py) formats the final output according to state["output_format"].

Practical Usage Examples

The Python API for SkillSpector supports diverse use cases, from one-off remote repository scans to batch processing of local skills.

Example 1: Scanning a Remote Repository with SARIF Output

This example demonstrates scanning a Git repository and extracting SARIF-formatted results:

from skillspector import graph
from skillspector.state import SkillspectorState

state: SkillspectorState = {
    "input_path": "https://github.com/example/my-skill",
    "output_format": "sarif",
    "use_llm": True,
}
result = graph.invoke(state)

sarif = result["sarif_report"]
print(sarif["runs"][0]["results"][0]["message"]["text"])

Example 2: Local Directory Analysis with Markdown Report

For local skill analysis without LLM processing:

import pathlib
from skillspector import create_graph

state = {
    "input_path": str(pathlib.Path("./my-local-skill").resolve()),
    "output_format": "markdown",
    "use_llm": False,
}
graph = create_graph()
result = graph.invoke(state)

# Write out the markdown report

pathlib.Path("skill_report.md").write_text(result["report_body"])

Example 3: Reusing the Graph for Multiple Scans

For performance-critical applications, reuse the pre-compiled graph instance across multiple scans:

from skillspector import graph

def scan(path: str, fmt: str = "terminal") -> dict:
    init = {
        "input_path": path,
        "output_format": fmt,
        "use_llm": True,
    }
    return graph.invoke(init)

# Scan two different skills

res1 = scan("https://github.com/foo/bar")
res2 = scan("./local-skill")
print(res1["risk_score"], res2["risk_score"])

Cleanup Requirements

When InputHandler creates temporary directories during remote resource processing, the Python API for SkillSpector returns the path in result["temp_dir_for_cleanup"]. The caller must delete these directories manually, as shown in src/skillspector/cli.py:

import shutil
if result.get("temp_dir_for_cleanup"):
    shutil.rmtree(result["temp_dir_for_cleanup"])

LLM Provider Integration

The Python API for SkillSpector implements pluggable LLM-provider abstractions through protocols defined in src/skillspector/providers/base.py. Provider implementations—including OpenAI (providers/openai/provider.py), Anthropic (providers/anthropic/provider.py), and NVIDIA (providers/nv_build/provider.py)—conform to the LLMProvider protocol.

These providers expose three capabilities:

  • Model metadata – Information about available models
  • Credential resolution – Authentication handling
  • Chat-model construction – Creating callable LLM instances

The workflow selects a provider based on the SKILLSPECTOR_PROVIDER environment variable, falling back to a default NVIDIA inference service when unspecified.

Summary

The Python API for SkillSpector provides a concise, powerful interface for programmatic skill analysis:

  • Primary symbols – create_graph() for fresh workflow instances, graph for singleton reuse, InputHandler for input normalization, and SkillspectorState for type-safe state management
  • Execution model – LangGraph-based workflow passing a shared state dictionary through specialized nodes
  • Input flexibility – Support for Git URLs, zip archives, local directories, and raw files via InputHandler
  • Output formats – SARIF, JSON, Markdown, and terminal formatting controlled via state configuration
  • Resource management – Automatic temporary directory creation with explicit cleanup requirements
  • LLM integration – Pluggable provider architecture supporting OpenAI, Anthropic, and NVIDIA backends

Frequently Asked Questions

What is the difference between create_graph() and graph?

create_graph() is a factory function that returns a newly compiled LangGraph workflow each time it is called, which is useful when you need a fresh state or customized compilation. graph is a pre-compiled singleton instance exported from the top-level package, optimized for reuse across multiple invocations to minimize compilation overhead.

How do I configure which LLM provider the Python API uses?

The workflow selects the LLM provider based on the SKILLSPECTOR_PROVIDER environment variable, as implemented in the provider resolution logic within src/skillspector/providers/base.py. Valid values include identifiers for OpenAI, Anthropic, and NVIDIA providers. If unset, the system defaults to the NVIDIA inference service.

What should I do with temp_dir_for_cleanup in the results?

When analyzing remote resources such as Git URLs or zip archives, InputHandler creates temporary directories to store the downloaded content. The graph.invoke() method returns the path to these directories in the temp_dir_for_cleanup key of the result dictionary. You must manually delete these directories using shutil.rmtree() when finished processing the results, as the API does not automatically handle filesystem cleanup.

Can I run SkillSpector analysis without using LLMs?

Yes. Set "use_llm": False in your SkillspectorState dictionary before invoking the graph. When this flag is disabled, the analyzer nodes skip LLM-based semantic analysis and rely solely on static analysis techniques, reducing execution time and eliminating API costs while still producing valid findings and risk scores.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →