+ );
+}
+
+export default HAXCapabilityManifest;
diff --git a/hax/artifacts/capability-manifest/description.ts b/hax/artifacts/capability-manifest/description.ts
new file mode 100644
index 0000000..6c866ea
--- /dev/null
+++ b/hax/artifacts/capability-manifest/description.ts
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2025 Cisco Systems, Inc. and its affiliates
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+export const CAPABILITY_MANIFEST_DESCRIPTION =
+ `Use capability manifest artifacts to display AI agent capabilities, constraints, and connection status to users. This component is essential for setting user expectations about what an AI agent can and cannot do, preventing the "Mental Model Mismatch" where users assume the agent has capabilities it doesn't possess.
+
+Best used for:
+- Agent initialization and handshake displays
+- Showing available tools and capabilities
+- Displaying runtime constraints and policies
+- Session status and connection information
+- Multi-agent capability comparison
+
+Structure your manifest with:
+1. Agent Header: Name, role, and status text to identify the agent
+2. Capabilities: List of available tools/features with their status (enabled, disabled, pending, error)
+3. Alerts: Runtime constraints, warnings, or important information
+4. Status Footer: Connection state and session identifier
+
+Capability statuses:
+- "enabled": Feature is available and ready to use (green checkmark)
+- "disabled": Feature is not available (gray circle)
+- "pending": Feature is loading or awaiting activation (yellow alert)
+- "error": Feature encountered an error (red X)
+
+Alert variants:
+- "warning": Orange - for constraints and cautions (e.g., "Requires approval for external API calls")
+- "error": Red - for critical issues or failures
+- "info": Blue - for informational notices
+- "success": Green - for positive confirmations
+
+Connection statuses:
+- "connected": Agent is online and ready (green dot)
+- "connecting": Establishing connection (pulsing yellow dot)
+- "disconnected": Agent is offline (gray dot)
+- "error": Connection failed (red dot)
+
+Best practices:
+- Always display capability manifest at session start (Phase 1) before user interaction
+- Keep capability names concise but descriptive
+- Use alerts sparingly - only for important constraints or warnings
+- Include session ID for debugging and tracking purposes
+- Group related capabilities when there are many (use capabilityGroups)
+- Set appropriate connection status to reflect actual agent state
+
+Don't use capability manifest for:
+- Displaying conversation history or messages
+- Showing detailed technical documentation
+- Complex data visualizations
+- Form inputs or user interactions` as const
diff --git a/hax/artifacts/capability-manifest/index.ts b/hax/artifacts/capability-manifest/index.ts
new file mode 100644
index 0000000..10b4681
--- /dev/null
+++ b/hax/artifacts/capability-manifest/index.ts
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2025 Cisco Systems, Inc. and its affiliates
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+export { HAXCapabilityManifest } from "./capability-manifest";
+export { useCapabilityManifestAction } from "./action";
+export type {
+ CapabilityManifestArtifact,
+ CapabilityManifestData,
+ Capability,
+ CapabilityStatus,
+ CapabilityGroup,
+ Alert,
+ AlertVariant,
+ AgentHeader,
+ AgentTag,
+ StatusInfo,
+ ConnectionStatus,
+ CardVariant,
+ SizeVariant,
+} from "./types";
+export {
+ CapabilityManifestArtifactZod,
+ CapabilityManifestDataZod,
+ CapabilityZod,
+ CapabilityStatusZod,
+ CapabilityGroupZod,
+ AlertZod,
+ AlertVariantZod,
+ AgentHeaderZod,
+ AgentTagZod,
+ StatusInfoZod,
+ ConnectionStatusZod,
+ CardVariantZod,
+ SizeVariantZod,
+} from "./types";
diff --git a/hax/artifacts/capability-manifest/types.ts b/hax/artifacts/capability-manifest/types.ts
new file mode 100644
index 0000000..92b83fb
--- /dev/null
+++ b/hax/artifacts/capability-manifest/types.ts
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2025 Cisco Systems, Inc. and its affiliates
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import z from "zod";
+
+// Capability status enum
+export const CapabilityStatusZod = z.enum([
+ "enabled",
+ "disabled",
+ "pending",
+ "error",
+]);
+export type CapabilityStatus = z.infer;
+
+// Alert variant enum
+export const AlertVariantZod = z.enum(["warning", "error", "info", "success"]);
+export type AlertVariant = z.infer;
+
+// Connection status enum
+export const ConnectionStatusZod = z.enum([
+ "connected",
+ "connecting",
+ "disconnected",
+ "error",
+]);
+export type ConnectionStatus = z.infer;
+
+// Card variant enum
+export const CardVariantZod = z.enum(["default", "outline", "ghost"]);
+export type CardVariant = z.infer;
+
+// Size variant enum
+export const SizeVariantZod = z.enum(["sm", "md", "lg"]);
+export type SizeVariant = z.infer;
+
+// Capability schema
+export const CapabilityZod = z.object({
+ id: z.string(),
+ name: z.string(),
+ description: z.string().optional(),
+ status: CapabilityStatusZod,
+ iconColor: z.string().optional(),
+ metadata: z.record(z.union([z.string(), z.number(), z.boolean()])).optional(),
+});
+export type Capability = z.infer;
+
+// Alert schema
+export const AlertZod = z.object({
+ id: z.string(),
+ title: z.string(),
+ description: z.string(),
+ variant: AlertVariantZod,
+ dismissible: z.boolean().optional(),
+});
+export type Alert = z.infer;
+
+// Capability group schema
+export const CapabilityGroupZod = z.object({
+ id: z.string(),
+ label: z.string(),
+ capabilities: z.array(CapabilityZod),
+ collapsible: z.boolean().optional(),
+ defaultCollapsed: z.boolean().optional(),
+});
+export type CapabilityGroup = z.infer;
+
+// Agent header schema
+export const AgentHeaderZod = z.object({
+ name: z.string(),
+ role: z.string().optional(),
+ statusText: z.string().optional(),
+});
+export type AgentHeader = z.infer;
+
+// Agent tag schema
+export const AgentTagZod = z.object({
+ label: z.string(),
+ color: z.string().optional(),
+ variant: z.enum(["default", "outline", "filled"]).optional(),
+});
+export type AgentTag = z.infer;
+
+// Status info schema
+export const StatusInfoZod = z.object({
+ status: ConnectionStatusZod,
+ label: z.string().optional(),
+ sessionId: z.string().optional(),
+ metadata: z.record(z.union([z.string(), z.number()])).optional(),
+ color: z.string().optional(),
+});
+export type StatusInfo = z.infer;
+
+// Main artifact data schema
+export const CapabilityManifestDataZod = z.object({
+ // Agent header
+ agentName: z.string().optional(),
+ agentRole: z.string().optional(),
+ statusText: z.string().optional(),
+ agentTags: z.array(AgentTagZod).optional(),
+
+ // Capabilities
+ capabilities: z.array(CapabilityZod).optional(),
+ capabilityGroups: z.array(CapabilityGroupZod).optional(),
+ capabilitiesLabel: z.string().optional(),
+ showCapabilities: z.boolean().optional(),
+
+ // Alerts
+ alerts: z.array(AlertZod).optional(),
+
+ // Status
+ connectionStatus: ConnectionStatusZod.optional(),
+ connectionLabel: z.string().optional(),
+ sessionId: z.string().optional(),
+ statusMetadata: z.record(z.union([z.string(), z.number()])).optional(),
+
+ // Customization
+ showSeparator: z.boolean().optional(),
+ showStatus: z.boolean().optional(),
+
+ // Styling
+ variant: CardVariantZod.optional(),
+ size: SizeVariantZod.optional(),
+ showShadow: z.boolean().optional(),
+});
+export type CapabilityManifestData = z.infer;
+
+// Full artifact schema
+export const CapabilityManifestArtifactZod = z.object({
+ id: z.string(),
+ type: z.literal("capability-manifest"),
+ data: CapabilityManifestDataZod,
+});
+export type CapabilityManifestArtifact = z.infer<
+ typeof CapabilityManifestArtifactZod
+>;
diff --git a/hax/artifacts/findings/README.md b/hax/artifacts/findings/README.md
new file mode 100644
index 0000000..f8aa5d6
--- /dev/null
+++ b/hax/artifacts/findings/README.md
@@ -0,0 +1,274 @@
+# Findings Artifact
+
+A HAX SDK component for displaying key insights, recommendations, or discoveries with their supporting sources.
+
+## Installation
+
+### Via HAX CLI (Recommended)
+
+First, ensure your project is initialized with HAX:
+
+```bash
+hax init
+```
+
+Then add the findings artifact:
+
+```bash
+hax add artifact findings
+```
+
+This will automatically:
+- Install the component files to your configured artifacts path
+- Install required dependencies
+- Update your `hax.config.json`
+
+### Dependencies
+
+The following dependencies will be installed automatically:
+
+```bash
+npm install react clsx tailwind-merge zod @copilotkit/react-core
+```
+
+## Usage
+
+### Basic Component Usage
+
+```tsx
+import { FindingsPanel, Finding } from "@/artifacts/findings";
+
+const findings: Finding[] = [
+ {
+ id: "1",
+ title: "Security Vulnerability Detected",
+ description: "SQL injection vulnerability found in user input handling",
+ sources: [
+ { label: "OWASP", href: "https://owasp.org" },
+ { label: "CVE-2024-1234" },
+ ],
+ },
+ {
+ id: "2",
+ title: "Performance Optimization",
+ description: "Database queries can be optimized with proper indexing",
+ sources: [{ label: "Analysis Report" }],
+ },
+];
+
+function App() {
+ return (
+
+ );
+}
+```
+
+### With CopilotKit Action
+
+```tsx
+import { useFindingsAction } from "@/artifacts/findings";
+
+function MyComponent() {
+ const addOrUpdateArtifact = (type, data) => {
+ // Handle artifact creation/update
+ console.log("Artifact:", type, data);
+ };
+
+ // Register the action with CopilotKit
+ useFindingsAction({ addOrUpdateArtifact });
+
+ return
Your component
;
+}
+```
+
+### HAX Wrapper Component
+
+```tsx
+import { HAXFindings, Finding } from "@/artifacts/findings";
+
+const findings: Finding[] = [
+ {
+ id: "1",
+ title: "Finding Title",
+ description: "Finding description",
+ sources: [{ label: "Source 1" }],
+ },
+];
+
+function App() {
+ return (
+
+ );
+}
+```
+
+## Components
+
+### FindingsPanel
+
+Main container component for displaying multiple findings.
+
+| Prop | Type | Required | Default | Description |
+|------|------|----------|---------|-------------|
+| `title` | `string` | Yes | - | Header title for the panel |
+| `findings` | `Finding[]` | Yes | - | Array of findings to display |
+| `sourcesLabel` | `string` | No | `"Sources:"` | Custom label for sources section |
+| `maxVisibleSources` | `number` | No | `2` | Max source chips before showing "+N" |
+| `className` | `string` | No | - | Additional CSS classes |
+
+### FindingsCard
+
+Individual finding card component.
+
+| Prop | Type | Required | Default | Description |
+|------|------|----------|---------|-------------|
+| `title` | `string` | Yes | - | Title text displayed in bold |
+| `description` | `string` | Yes | - | Description text below the title |
+| `sources` | `string[]` | No | `[]` | Array of source labels |
+| `showSources` | `boolean` | No | `true` | Whether to show sources section |
+| `sourcesLabel` | `string` | No | `"Sources:"` | Custom sources label |
+| `maxVisibleSources` | `number` | No | - | Max chips before overflow |
+
+### SourceChips
+
+Displays a row of source chips with overflow handling.
+
+| Prop | Type | Required | Default | Description |
+|------|------|----------|---------|-------------|
+| `sources` | `string[]` | Yes | - | Array of source labels |
+| `label` | `string` | No | `"Sources:"` | Label shown before chips |
+| `maxVisible` | `number` | No | - | Max chips before "+N" |
+| `maxChipWidth` | `number \| string` | No | - | Max width for individual chips |
+
+### SourceChip
+
+Individual source chip component.
+
+| Prop | Type | Required | Default | Description |
+|------|------|----------|---------|-------------|
+| `label` | `string` | Yes | - | Text label to display |
+| `maxWidth` | `number \| string` | No | - | Max width (truncates with ellipsis) |
+| `isCountChip` | `boolean` | No | `false` | Whether this is a "+N" count chip |
+| `truncate` | `boolean` | No | `false` | Allow chip to shrink and truncate |
+
+## Schema
+
+### Finding Type
+
+```typescript
+interface Finding {
+ id: string; // Unique identifier
+ title: string; // Title of the finding
+ description: string; // Description/recommendation
+ sources?: Array<{ // Optional source references
+ label: string; // Display label
+ href?: string; // Optional link URL
+ }>;
+}
+```
+
+### Zod Schema
+
+```typescript
+import { FindingsArtifactZod } from "@/artifacts/findings";
+
+// Schema structure:
+const FindingsArtifactZod = z.object({
+ id: z.string(),
+ type: z.literal("findings"),
+ data: z.object({
+ title: z.string(),
+ findings: z.array(z.object({
+ id: z.string(),
+ title: z.string(),
+ description: z.string(),
+ sources: z.array(z.object({
+ label: z.string(),
+ href: z.string().optional(),
+ })).optional(),
+ })),
+ sourcesLabel: z.string().optional(),
+ maxVisibleSources: z.number().optional(),
+ }),
+});
+```
+
+## CopilotKit Action
+
+The `useFindingsAction` hook registers a `create_findings` action with CopilotKit.
+
+### Action Parameters
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------|
+| `title` | `string` | Yes | Header title for the findings panel |
+| `findingsJson` | `string` | Yes | JSON string of findings array |
+| `sourcesLabel` | `string` | No | Custom label for sources (default: "Sources:") |
+| `maxVisibleSources` | `number` | No | Max source chips before "+N" (default: 2) |
+
+### findingsJson Format
+
+```json
+[
+ {
+ "id": "unique-id-1",
+ "title": "Finding Title",
+ "description": "Detailed description of the finding",
+ "sources": [
+ { "label": "Source Name", "href": "https://example.com" },
+ { "label": "Another Source" }
+ ]
+ }
+]
+```
+
+## Best Practices
+
+- Keep finding titles concise and actionable (under 10 words)
+- Provide clear, specific descriptions that explain the finding's significance
+- Include relevant sources to build credibility and enable follow-up
+- Limit to 3-7 findings per panel to maintain readability
+- Use consistent source labeling conventions
+
+## When to Use
+
+Use findings artifacts for:
+- Research summaries
+- Analysis results
+- Audit findings
+- Security assessments
+- Any situation where users need to see multiple findings with source attribution
+
+Avoid using findings for:
+- Simple lists without context
+- Single-item displays
+- Overly long descriptions (break into separate findings instead)
+
+## Exports
+
+```typescript
+// Components
+export { HAXFindings, FindingsPanel, FindingsCard, SourceChips, SourceChip }
+
+// Types
+export type { Finding, FindingsPanelProps, FindingsCardProps, SourceChipsProps, SourceChipProps }
+
+// Action Hook
+export { useFindingsAction }
+
+// Schema
+export { FindingsArtifactZod }
+export type { FindingsArtifact }
+```
+
+## License
+
+Apache License 2.0 - Copyright 2025 Cisco Systems, Inc. and its affiliates
diff --git a/hax/artifacts/findings/action.ts b/hax/artifacts/findings/action.ts
new file mode 100644
index 0000000..4f0c29c
--- /dev/null
+++ b/hax/artifacts/findings/action.ts
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2025 Cisco Systems, Inc. and its affiliates
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { useCopilotAction } from "@copilotkit/react-core";
+import { FindingsArtifact } from "./types";
+import { FINDINGS_DESCRIPTION } from "./description";
+
+interface UseFindingsActionProps {
+ addOrUpdateArtifact: (type: "findings", data: FindingsArtifact["data"]) => void;
+}
+
+export const useFindingsAction = ({ addOrUpdateArtifact }: UseFindingsActionProps) => {
+ useCopilotAction({
+ name: "create_findings",
+ description: FINDINGS_DESCRIPTION,
+ parameters: [
+ {
+ name: "title",
+ type: "string",
+ description: "Panel title for the findings",
+ required: true,
+ },
+ {
+ name: "findingsJson",
+ type: "string",
+ description: "JSON string of findings array: [{id, title, description, sources?: [{label, href?}]}]",
+ required: true,
+ },
+ ],
+ handler: async (args) => {
+ const { title, findingsJson } = args;
+ const findings = JSON.parse(findingsJson);
+
+ addOrUpdateArtifact("findings", { title, findings });
+
+ return `Created findings panel "${title}" with ${findings.length} findings`;
+ },
+ });
+};
diff --git a/hax/artifacts/findings/description.ts b/hax/artifacts/findings/description.ts
new file mode 100644
index 0000000..c3d8aa3
--- /dev/null
+++ b/hax/artifacts/findings/description.ts
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2025 Cisco Systems, Inc. and its affiliates
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+export const FINDINGS_DESCRIPTION =
+ `Use findings panels for answering factual questions, research queries, and displaying analysis results with source attribution. This is the PRIMARY artifact for questions like "Is X safe?", "What is Y?", "How does Z work?".
+
+PREFER findings over thinking-process for simple research/factual questions. Use thinking-process only when user explicitly asks to see reasoning steps.
+
+Best for:
+- Factual questions and research queries
+- AI research results and analysis summaries
+- Security findings and audit results
+- Recommendations with supporting evidence
+
+Include a panel title and one or more findings. Each finding should have:
+- Clear title summarizing the key insight
+- Detailed description with the answer/information
+- Relevant sources for credibility and verification
+
+Write clear, actionable finding descriptions. Include all relevant sources for each finding. Group related findings together. Keep findings focused and specific. Ensure each finding has a unique ID.
+
+Don't use for: Complex multi-step debugging workflows (use thinking-process), code examples (use code-editor), or simple status updates.` as const;
diff --git a/hax/artifacts/findings/findings.tsx b/hax/artifacts/findings/findings.tsx
new file mode 100644
index 0000000..6183a26
--- /dev/null
+++ b/hax/artifacts/findings/findings.tsx
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2025 Cisco Systems, Inc. and its affiliates
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from "react";
+import { FindingsPanel } from "@/components/findings";
+import type { FindingsArtifact } from "./types";
+
+export interface HAXFindingsProps {
+ title: string;
+ findings: FindingsArtifact["data"]["findings"];
+ onSourceClick?: (source: string, index: number, findingId: string) => void;
+}
+
+export function HAXFindings({
+ title,
+ findings,
+ onSourceClick,
+}: HAXFindingsProps) {
+ return (
+
+
+
+ );
+}
diff --git a/hax/artifacts/findings/index.ts b/hax/artifacts/findings/index.ts
new file mode 100644
index 0000000..e44c2b0
--- /dev/null
+++ b/hax/artifacts/findings/index.ts
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2025 Cisco Systems, Inc. and its affiliates
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+export { HAXFindings } from "./findings";
+export { useFindingsAction } from "./action";
+export type { FindingsArtifact, Finding, Source } from "./types";
+export { FindingsArtifactZod, FindingZod, SourceZod } from "./types";
diff --git a/hax/artifacts/findings/types.ts b/hax/artifacts/findings/types.ts
new file mode 100644
index 0000000..156c547
--- /dev/null
+++ b/hax/artifacts/findings/types.ts
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2025 Cisco Systems, Inc. and its affiliates
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { z } from "zod";
+
+export const SourceZod = z.object({
+ label: z.string(),
+ href: z.string().optional(),
+});
+
+export const FindingZod = z.object({
+ id: z.string(),
+ title: z.string(),
+ description: z.string(),
+ sources: z.array(SourceZod).optional(),
+});
+
+export const FindingsArtifactZod = z.object({
+ id: z.string(),
+ type: z.literal("findings"),
+ data: z.object({
+ title: z.string(),
+ findings: z.array(FindingZod),
+ }),
+});
+
+export type FindingsArtifact = z.infer;
+export type Finding = z.infer;
+export type Source = z.infer;
diff --git a/hax/artifacts/inline-rationale/README.md b/hax/artifacts/inline-rationale/README.md
new file mode 100644
index 0000000..bdc0baa
--- /dev/null
+++ b/hax/artifacts/inline-rationale/README.md
@@ -0,0 +1,224 @@
+# Inline Rationale Component
+
+A React component for displaying AI-driven assessments, decisions, and explanations with intent-based visual theming. Ideal for security assessments, code reviews, policy decisions, and any AI-generated rationale that needs clear visual distinction.
+
+## Installation
+
+### Prerequisites
+
+- React 18+
+- Tailwind CSS configured in your project
+- HAX CLI installed globally
+
+### Initialize HAX in Your Project
+
+```bash
+hax init
+```
+
+This sets up the necessary configuration and dependencies in your project.
+
+### Add the Inline Rationale Component
+
+```bash
+hax add artifact inline-rationale
+```
+
+This command will:
+- Install the component files to your project
+- Add required dependencies (`zod`, `@copilotkit/react-core`)
+- Set up the `cn` utility if not already present
+
+## Usage
+
+### Basic Usage
+
+```tsx
+import { InlineRationale } from "@/artifacts/inline-rationale"
+
+function App() {
+ return (
+
+ )
+}
+```
+
+### HAX Wrapper Component
+
+Use `HAXInlineRationale` for a pre-styled wrapper with margin:
+
+```tsx
+import { HAXInlineRationale } from "@/artifacts/inline-rationale"
+
+function App() {
+ return (
+
+ )
+}
+```
+
+### Collapsible Content
+
+Enable collapse/expand functionality:
+
+```tsx
+ console.log("Collapsed:", collapsed)}
+/>
+```
+
+### CopilotKit Integration
+
+Use the action hook for AI-driven rationale creation:
+
+```tsx
+import { useInlineRationaleAction } from "@/artifacts/inline-rationale"
+
+function ChatComponent() {
+ const [artifacts, setArtifacts] = useState([])
+
+ useInlineRationaleAction({
+ addOrUpdateArtifact: (type, data) => {
+ setArtifacts(prev => [...prev, { type, data, id: Date.now() }])
+ }
+ })
+
+ return (
+ // Your chat UI that renders artifacts
+ )
+}
+```
+
+## Props
+
+### InlineRationaleProps
+
+| Prop | Type | Required | Default | Description |
+|------|------|----------|---------|-------------|
+| `id` | `string` | Yes | - | Unique identifier |
+| `assessmentType` | `string` | Yes | - | Type of assessment (e.g., "security_assessment", "code_review") |
+| `intent` | `Intent` | Yes | - | Visual theme: "warn", "approve", "block", "inform" |
+| `title` | `string` | Yes | - | Display title |
+| `description` | `string` | Yes | - | Main description paragraph |
+| `summary` | `AssessmentSummary` | Yes | - | Summary with impact and exploitability |
+| `rationale` | `RationaleItem[]` | Yes | - | Detail items as label/value pairs |
+| `confidence` | `number` | Yes | - | Confidence score (0-100) |
+| `metadata` | `Metadata` | No | - | Optional tracking metadata |
+| `collapsed` | `boolean` | No | `false` | Initial collapsed state |
+| `collapsible` | `boolean` | No | `false` | Enable collapse toggle |
+| `onCollapseChange` | `(collapsed: boolean) => void` | No | - | Collapse change callback |
+| `className` | `string` | No | - | Additional CSS classes |
+
+## Types
+
+### Intent
+
+```typescript
+type Intent = "warn" | "approve" | "block" | "inform"
+```
+
+Visual themes:
+- `block` (red): Security vulnerabilities, access denials, critical issues
+- `warn` (yellow): Performance issues, warnings that need attention
+- `approve` (green): Approvals, successful validations
+- `inform` (blue): General information, neutral notifications
+
+### ImpactLevel
+
+```typescript
+type ImpactLevel = "low" | "medium" | "high" | "critical"
+```
+
+### ExploitabilityLevel
+
+```typescript
+type ExploitabilityLevel = "none" | "low" | "medium" | "high"
+```
+
+### AssessmentSummary
+
+```typescript
+interface AssessmentSummary {
+ impact: ImpactLevel
+ exploitability: ExploitabilityLevel
+ tags?: string[]
+}
+```
+
+### RationaleItem
+
+```typescript
+interface RationaleItem {
+ label: string
+ value: string
+}
+```
+
+### Metadata
+
+```typescript
+interface Metadata {
+ generated_by: "ai" | "human" | "hybrid"
+ model?: string
+ version?: string
+ timestamp?: string
+}
+```
+
+## Files
+
+| File | Description |
+|------|-------------|
+| `inline-rationale.tsx` | Main React component with `InlineRationale` and `HAXInlineRationale` |
+| `types.ts` | Zod schemas and TypeScript type definitions |
+| `action.ts` | CopilotKit integration hook (`useInlineRationaleAction`) |
+| `description.ts` | AI prompt guidance constant |
+| `index.ts` | Module exports |
diff --git a/hax/artifacts/inline-rationale/action.ts b/hax/artifacts/inline-rationale/action.ts
new file mode 100644
index 0000000..1600fa7
--- /dev/null
+++ b/hax/artifacts/inline-rationale/action.ts
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2025 Cisco Systems, Inc. and its affiliates
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { useCopilotAction } from "@copilotkit/react-core";
+import z from "zod";
+import { INLINE_RATIONALE_DESCRIPTION } from "./description";
+import type {
+ InlineRationaleArtifact,
+ Intent,
+ ImpactLevel,
+ ExploitabilityLevel,
+} from "./types";
+
+const RationaleItemZod = z.object({
+ label: z.string(),
+ value: z.string(),
+});
+
+interface UseInlineRationaleActionProps {
+ addOrUpdateArtifact: (
+ type: "inline-rationale",
+ data: InlineRationaleArtifact["data"],
+ ) => void;
+}
+
+export const useInlineRationaleAction = ({
+ addOrUpdateArtifact,
+}: UseInlineRationaleActionProps) => {
+ useCopilotAction({
+ name: "create_inline_rationale",
+ description: INLINE_RATIONALE_DESCRIPTION,
+ parameters: [
+ {
+ name: "title",
+ type: "string",
+ description: "Display title for the rationale card",
+ required: true,
+ },
+ {
+ name: "description",
+ type: "string",
+ description: "Main paragraph text explaining the assessment",
+ required: true,
+ },
+ {
+ name: "intent",
+ type: "string",
+ description:
+ "Visual theme intent: 'block' (red, critical issues), 'warn' (yellow, warnings), 'approve' (green, approvals), 'inform' (blue, information)",
+ required: true,
+ },
+ {
+ name: "assessmentType",
+ type: "string",
+ description:
+ "Type of assessment (e.g., 'security_assessment', 'code_review', 'policy_decision', 'performance_alert')",
+ required: true,
+ },
+ {
+ name: "impact",
+ type: "string",
+ description: "Impact level: 'low', 'medium', 'high', 'critical'",
+ required: true,
+ },
+ {
+ name: "exploitability",
+ type: "string",
+ description: "Exploitability level: 'none', 'low', 'medium', 'high'",
+ required: true,
+ },
+ {
+ name: "confidence",
+ type: "number",
+ description: "Confidence score 0-100 (badge color derived from intent)",
+ required: true,
+ },
+ {
+ name: "rationaleJson",
+ type: "string",
+ description:
+ "JSON string of rationale array with {label, value} objects for detail items",
+ required: true,
+ },
+ {
+ name: "tagsJson",
+ type: "string",
+ description:
+ "Optional JSON string of tags array (e.g., ['v2.4.0', 'Production'])",
+ required: false,
+ },
+ {
+ name: "collapsible",
+ type: "boolean",
+ description: "Whether the content can be collapsed/expanded",
+ required: false,
+ },
+ {
+ name: "collapsed",
+ type: "boolean",
+ description: "Initial collapsed state (default: false)",
+ required: false,
+ },
+ ],
+ handler: async (args) => {
+ try {
+ const {
+ title,
+ description,
+ intent,
+ assessmentType,
+ impact,
+ exploitability,
+ confidence,
+ rationaleJson,
+ tagsJson,
+ collapsible,
+ collapsed,
+ } = args;
+
+ // Parse and validate rationale JSON with Zod
+ let rationale: z.infer[] = [];
+ if (rationaleJson) {
+ const parsed = JSON.parse(rationaleJson);
+ rationale = z.array(RationaleItemZod).parse(parsed);
+ }
+
+ // Parse and validate tags JSON with Zod
+ let tags: string[] | undefined;
+ if (tagsJson) {
+ const parsed = JSON.parse(tagsJson);
+ tags = z.array(z.string()).parse(parsed);
+ }
+
+ addOrUpdateArtifact("inline-rationale", {
+ assessmentType,
+ intent: intent as Intent,
+ title,
+ description,
+ summary: {
+ impact: impact as ImpactLevel,
+ exploitability: exploitability as ExploitabilityLevel,
+ tags,
+ },
+ rationale,
+ confidence,
+ collapsible,
+ collapsed,
+ });
+
+ return `Created inline rationale "${title}"`;
+ } catch (error) {
+ console.error("Error in create_inline_rationale handler:", error);
+ const errorMessage =
+ error instanceof Error ? error.message : "Unknown error";
+ return `Failed to create inline rationale: ${errorMessage}`;
+ }
+ },
+ });
+};
diff --git a/hax/artifacts/inline-rationale/description.ts b/hax/artifacts/inline-rationale/description.ts
new file mode 100644
index 0000000..d487bb4
--- /dev/null
+++ b/hax/artifacts/inline-rationale/description.ts
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2025 Cisco Systems, Inc. and its affiliates
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+export const INLINE_RATIONALE_DESCRIPTION =
+ `Use inline-rationale artifacts to display AI-driven assessments, decisions, and explanations with intent-based visual theming. Best for security assessments, code reviews, policy decisions, and any AI-generated rationale that needs clear visual distinction.
+
+Schema (Single Source of Truth):
+- intent: Drives the visual theme (warn=yellow, block=red, approve=green, inform=blue)
+- description: Main paragraph text explaining the assessment
+- summary: { impact, exploitability } for generating badges
+- rationale: Detail items as { label, value } pairs
+- confidence: 0-100 score (badge color comes from intent)
+
+Choose the appropriate intent based on the nature of the assessment:
+- "block" (red): Security vulnerabilities, access denials, critical issues requiring immediate action
+- "warn" (yellow): Performance issues, potential problems, warnings that need attention
+- "approve" (green): Code review approvals, successful validations, positive outcomes
+- "inform" (blue): General information, deployment summaries, neutral notifications
+
+Impact levels: "low", "medium", "high", "critical"
+Exploitability levels: "none", "low", "medium", "high"
+
+Best practices:
+- Use clear, actionable titles
+- Keep description focused on the key message
+- Limit rationale items to 3-6 most important factors
+- Match intent to the severity/nature of the assessment
+- Include confidence when the AI has varying certainty
+
+Don't use inline-rationale for simple text responses. Use it when you need to communicate structured AI reasoning with visual distinction based on the nature of the decision.` as const
diff --git a/hax/artifacts/inline-rationale/index.ts b/hax/artifacts/inline-rationale/index.ts
new file mode 100644
index 0000000..03a2b8f
--- /dev/null
+++ b/hax/artifacts/inline-rationale/index.ts
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2025 Cisco Systems, Inc. and its affiliates
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+export { InlineRationale, HAXInlineRationale } from "./inline-rationale"
+export type { InlineRationaleProps } from "./inline-rationale"
+export { useInlineRationaleAction } from "./action"
+export type {
+ InlineRationaleArtifact,
+ Intent,
+ ImpactLevel,
+ ExploitabilityLevel,
+ GeneratedBy,
+ AssessmentSummary,
+ RationaleItem,
+ Metadata,
+} from "./types"
+export { InlineRationaleArtifactZod } from "./types"
+export { INLINE_RATIONALE_DESCRIPTION } from "./description"
diff --git a/hax/artifacts/inline-rationale/inline-rationale.tsx b/hax/artifacts/inline-rationale/inline-rationale.tsx
new file mode 100644
index 0000000..ea355d1
--- /dev/null
+++ b/hax/artifacts/inline-rationale/inline-rationale.tsx
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2025 Cisco Systems, Inc. and its affiliates
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+"use client";
+
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+import type {
+ Intent,
+ ImpactLevel,
+ ExploitabilityLevel,
+ AssessmentSummary,
+ RationaleItem,
+ Metadata,
+} from "./types";
+
+// =============================================================================
+// Component Props
+// =============================================================================
+
+export interface InlineRationaleProps {
+ /** Unique identifier */
+ id: string;
+ /** Assessment type - flexible string (e.g., "security_assessment", "code_review") */
+ assessmentType: string;
+ /** Intent drives visual theme: warn=yellow, block=red, approve=green, inform=blue */
+ intent: Intent;
+ /** Display title */
+ title: string;
+ /** Main description paragraph */
+ description: string;
+ /** Structured summary for badges (impact + exploitability) */
+ summary: AssessmentSummary;
+ /** Detail items displayed as "Label: Value" pairs */
+ rationale: RationaleItem[];
+ /** Confidence score 0-100 (badge color derived from intent) */
+ confidence: number;
+ /** Optional metadata */
+ metadata?: Metadata;
+ /** Optional: collapsed state */
+ collapsed?: boolean;
+ /** Optional: enable collapse toggle */
+ collapsible?: boolean;
+ /** Optional: collapse change callback */
+ onCollapseChange?: (collapsed: boolean) => void;
+ /** Optional: additional CSS classes */
+ className?: string;
+}
+
+// =============================================================================
+// Internal Style Mappings
+// =============================================================================
+
+type VariantKey = "critical" | "warning" | "success" | "info";
+type BadgeVariant = "default" | "success" | "warning" | "critical";
+
+/** Intent → card variant (background/border) */
+const INTENT_TO_VARIANT: Record = {
+ warn: "warning",
+ approve: "success",
+ block: "critical",
+ inform: "info",
+};
+
+/** Intent → confidence badge color */
+const INTENT_TO_BADGE_VARIANT: Record = {
+ warn: "warning",
+ approve: "success",
+ block: "critical",
+ inform: "success",
+};
+
+/** Card variant styles */
+const VARIANT_STYLES: Record<
+ VariantKey,
+ { background: string; border: string }
+> = {
+ critical: {
+ background: "bg-[#fff1f2]",
+ border: "border-[#e11d48]",
+ },
+ warning: {
+ background: "bg-[#fffbeb]",
+ border: "border-[#f59e0b]",
+ },
+ success: {
+ background: "bg-[#ecfdf5]",
+ border: "border-[#059669]",
+ },
+ info: {
+ background: "bg-[#eff6ff]",
+ border: "border-[#3b82f6]",
+ },
+};
+
+/** Badge variant styles */
+const BADGE_STYLES: Record = {
+ default: "bg-[#f1f5f9] text-[#0f172a]",
+ success: "bg-[#a7f3d0] text-[#047857]",
+ warning: "bg-[#fde68a] text-[#b45309]",
+ critical: "bg-[#fecaca] text-[#dc2626]",
+};
+
+/** Impact level labels */
+const IMPACT_LABELS: Record = {
+ low: "Low Impact",
+ medium: "Medium Impact",
+ high: "High Impact",
+ critical: "Critical Impact",
+};
+
+/** Exploitability level labels */
+const EXPLOITABILITY_LABELS: Record = {
+ none: "Exploitability : None",
+ low: "Exploitability : Low",
+ medium: "Exploitability : Medium",
+ high: "Exploitability : High",
+};
+
+// =============================================================================
+// Component
+// =============================================================================
+
+export function InlineRationale({
+ id,
+ assessmentType,
+ intent,
+ title,
+ description,
+ summary,
+ rationale,
+ confidence,
+ collapsed = false,
+ collapsible = false,
+ onCollapseChange,
+ className,
+}: InlineRationaleProps) {
+ const [isCollapsed, setIsCollapsed] = React.useState(collapsed);
+
+ React.useEffect(() => {
+ setIsCollapsed(collapsed);
+ }, [collapsed]);
+
+ const handleToggleCollapse = () => {
+ if (collapsible) {
+ const newState = !isCollapsed;
+ setIsCollapsed(newState);
+ onCollapseChange?.(newState);
+ }
+ };
+
+ // Get card variant from intent
+ const variant = INTENT_TO_VARIANT[intent];
+ const variantStyle = VARIANT_STYLES[variant];
+
+ // Build badges: Impact (gray) → Exploitability (gray) → Confidence (colored) → Tags (gray)
+ const badges = [
+ {
+ label: IMPACT_LABELS[summary.impact],
+ variant: "default" as BadgeVariant,
+ },
+ {
+ label: EXPLOITABILITY_LABELS[summary.exploitability],
+ variant: "default" as BadgeVariant,
+ },
+ {
+ label: `${confidence}% Confidence`,
+ variant: INTENT_TO_BADGE_VARIANT[intent],
+ },
+ ...(summary.tags?.map((tag) => ({
+ label: tag,
+ variant: "default" as BadgeVariant,
+ })) || []),
+ ];
+
+ return (
+