# Grasshopper2.Components.Descriptive namespace

Assembly: [Grasshopper2](https://developer.rhino3d.com/api/gh2/assembly/grasshopper2.md)

## Interfaces

- [IAiBackend](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.iaibackend.md): Abstraction over an LLM provider. Implementations wrap the actual HTTP + JSON dance for a specific service (Anthropic, OpenAI, Google, OpenRouter, ...) or for a development stand-in like the play-act backend.
- [IAiKeyStore](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.iaikeystore.md): Persistent storage for LLM-provider API keys. Implementations use the platform's native secret store: macOS Keychain on macOS, DPAPI-encrypted file on Windows. Keys are scoped to the current OS user account and to a specific [AiProvider](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aiprovider.md), so an Anthropic key and a Google key can coexist.
- [IAiSdkDocs](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.iaisdkdocs.md): Lookup service that surfaces Grasshopper2 SDK information to the model during code generation. Implementations are expected to be fast and in-process -- the model calls these tools multiple times per generation and tool latency directly extends the user's wait time.

## Classes

- [AiBackendResponse](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aibackendresponse.md): What the backend returned for a single turn. Either text (the model declined to call a tool) or a structured tool call. Exactly one of [AiBackendResponse.Text](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aibackendresponse/text.md) and [AiBackendResponse.ToolCall](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aibackendresponse/toolcall.md) is populated.
- [AiBehaviourSummary](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aibehavioursummary.md): Plain-English description of what the generated code does, surfaced to the user for confirmation before the component is wired up. Catches intent mismatch at the spec level, which is the only level non-programmers can validate at.
- [AiCompilationResult](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aicompilationresult.md): Outcome of compiling LLM source. On success carries the compiled [AiComponentLogic](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aicomponentlogic.md); on failure carries diagnostics for the next round.
- [AiComponent](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aicomponent.md)
- [AiComponentAttributes](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aicomponentattributes.md): Custom attributes for [AiComponent](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aicomponent.md). Routes a double-click on the component body to the prompt-and-conversation flow.
- [AiComponentLogic](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aicomponentlogic.md): Base class for the logic hosted inside an [AiComponent](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aicomponent.md).
- [AiComponentStateAction](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aicomponentstateaction.md): Stores the [AiComponent.UserPrompt](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aicomponent/userprompt.md), [AiComponent.SourceCode](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aicomponent/sourcecode.md), [AiComponent.LastInteractionMessage](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aicomponent/lastinteractionmessage.md), and the info field of the component nomen as an undo record. Parameters are not stored -- they are derived from SourceCode via [AiComponent.PreProcess(Solution)](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aicomponent/preprocess.md) and lazily rebuilt on the next solve after undo/redo.
- [AiDiagnostic](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aidiagnostic.md): A single diagnostic produced while compiling LLM-generated source.
- [AiDocHit](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aidochit.md): A single search result from the SDK docs. Carries enough for the model to decide whether to use this symbol; the full content (with examples, pitfalls, etc.) lives in the doc body that [IAiSdkDocs](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.iaisdkdocs.md) returns separately if asked.
- [AiKeyStore](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aikeystore.md): Factory for the platform-appropriate [IAiKeyStore](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.iaikeystore.md). Picks [WindowsDpapiKeyStore](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.windowsdpapikeystore.md) on Windows and [MacKeychainKeyStore](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.mackeychainkeystore.md) elsewhere (which in practice means macOS for Rhino).
- [AiMessage](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aimessage.md): A single message in an AI conversation. The shape varies by role: system/user/assistant text messages carry only [AiMessage.Text](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aimessage/text.md); assistant tool-call messages carry only [AiMessage.ToolCall](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aimessage/toolcall.md); tool result messages carry [AiMessage.ToolName](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aimessage/toolname.md) plus the result in [AiMessage.Text](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aimessage/text.md). Construct via the static factory methods.
- [AiPromptEntry](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aipromptentry.md): One round of conversation history: a user prompt and the response it produced. Lets the user step back to a previous working version after a bad refinement, and gives the LLM context for follow-up requests without re-explaining from scratch.
- [AiProviderInfo](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aiproviderinfo.md): Per-provider strings used by the sign-in dialog and the right-click panel: human-readable name, the URL where the user manages their account / API keys / usage, and the dialog explanation text.
- [AiSecurityReport](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aisecurityreport.md): Output of the pre-compilation syntax scan. Empty [AiSecurityReport.Violations](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aisecurityreport/violations.md) means the source passes the static safety check; non-empty means it must be rejected and surfaced to the user.
- [AiSecurityViolation](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aisecurityviolation.md): A single banned-symbol occurrence found by the syntax-tree scan.
- [AiTool](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aitool.md): Definition of a tool that the model is allowed to invoke. The provider sends the name, description, and JSON Schema for the parameters on every call, and the model emits an [AiToolCall](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aitoolcall.md) matching one of the offered tools.
- [AiToolCall](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aitoolcall.md): A single tool invocation emitted by the model. Carries the tool name and the raw JSON-encoded arguments to be parsed by the tool-specific handler.
- [AiTools](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aitools.md): The fixed set of tools exposed to the model during code generation. The model picks one per turn; the tool name drives the routing logic on the host side, replacing any need to parse prose. Two are terminal ([AiTools.Compile](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aitools/compile.md) delivers final code, [AiTools.Abandon](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aitools/abandon.md) gives up); the rest progress the conversation.
- [AnthropicAiBackend](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.anthropicaibackend.md): IAiBackend implementation talking to Anthropic's Messages API directly over HTTPS. Supports tool use and prompt caching of the system block, which gives a ~10x cost reduction on cached input tokens once the cache is warm.
- [GeminiAiBackend](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.geminiaibackend.md): IAiBackend implementation talking to Google's Gemini generateContent endpoint. The same conversation loop, tools, and docs corpus that drive the Anthropic backend work here -- only the wire format and a few naming conventions differ (role "model" instead of "assistant", systemInstruction as a top-level field, functionCall / functionResponse parts, no tool-use ids needed for round-tripping). Gemini has a no-credit-card free tier that's adequate for tyre-kicking and light usage. Quality is below Claude Opus on code generation but Flash is adequate for simple components and trivial to test.
- [InMemoryAiSdkDocs](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.inmemoryaisdkdocs.md): V1 stand-in for the real SDK docs. Holds a small hand-authored corpus of the Grasshopper2 surface area the model actually needs (parameter construction, IDataAccess patterns, the AiComponentLogic contract). Swap out for a JSON-loaded implementation once the corpus is big enough that hand-editing this file becomes painful.
- [InteractionStatistics](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.interactionstatistics.md): Tracks what the AI conversation loop has been doing on a given AiComponent: the current phase plus running counters for each kind of event (model calls, docs lookups, clarifications, compilation attempts, various failure modes). Also owns the lifecycle handle for the current run -- the [SolutionId](https://developer.rhino3d.com/api/gh2/type/grasshopper2.doc.solutionid.md) identifying it and the [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken) that aborts it. The component's attributes class draws from this state. Every property setter fires [InteractionStatistics.Changed](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.interactionstatistics/changed.md) on a real change. The owning component subscribes once and invalidates the canvas on Changed, so the drawing refreshes automatically as the loop progresses.
- [MacKeychainKeyStore](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.mackeychainkeystore.md): macOS implementation of [IAiKeyStore](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.iaikeystore.md). Stores each key in the user's login keychain via the `/usr/bin/security` command-line tool, under a per-provider service name. The key is encrypted at rest by the OS and gated by the user's login. Caveat: during Set/Delete the API key briefly appears as an argument in process listings. The keychain entry itself is properly encrypted. A future improvement would be P/Invoke to Security.framework's SecKeychain APIs directly, which avoids the argv exposure.
- [OpenAiCompatibleBackend](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.openaicompatiblebackend.md): IAiBackend implementation talking the OpenAI Chat Completions wire format. The system/user/assistant message shape is flat (no nested content blocks like Anthropic, no separate systemInstruction like Gemini) and tool calls round-trip through an explicit tool_call_id. Forces tool_choice = "required" so the model cannot answer in prose -- the conversation loop expects every turn to be a tool invocation. This class is provider-neutral: OpenAI and DeepSeek both speak the same schema, differing only in endpoint URL and default model. The caller supplies those at construction.
- [WindowsDpapiKeyStore](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.windowsdpapikeystore.md): Windows implementation of [IAiKeyStore](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.iaikeystore.md). Encrypts each key with DPAPI (current user scope, so other Windows accounts on the same machine cannot read it) and writes the ciphertext to a per-provider file under %APPDATA%\McNeel\Grasshopper2.

## Enums

- [AiDiagnosticSeverity](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aidiagnosticseverity.md)
- [AiMessageRole](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aimessagerole.md): Role of a single message in an AI conversation. Mirrors the standard system/user/assistant/tool roles used by all major LLM provider APIs.
- [AiProvider](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.aiprovider.md): The set of LLM providers the AI Component knows how to talk to. Each value has a corresponding [IAiBackend](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.iaibackend.md) implementation and is also used to scope per-provider entries in [IAiKeyStore](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.iaikeystore.md).
- [InteractionState](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.interactionstate.md): Phase the conversation loop is currently in. Tracked on [InteractionStatistics](https://developer.rhino3d.com/api/gh2/type/grasshopper2.components.descriptive.interactionstatistics.md) so the component's attributes can render different visual states (icon, colour, label).
