diff --git a/site/src/pages/AgentsPage/components/ChatElements/tools/ReadSkillTool.tsx b/site/src/pages/AgentsPage/components/ChatElements/tools/ReadSkillTool.tsx
new file mode 100644
index 0000000000..6a35d426d9
--- /dev/null
+++ b/site/src/pages/AgentsPage/components/ChatElements/tools/ReadSkillTool.tsx
@@ -0,0 +1,63 @@
+import { BookOpenIcon, LoaderIcon, TriangleAlertIcon } from "lucide-react";
+import type React from "react";
+import { ScrollArea } from "#/components/ScrollArea/ScrollArea";
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "#/components/Tooltip/Tooltip";
+import { cn } from "#/utils/cn";
+import { Response } from "../Response";
+import { ToolCollapsible } from "./ToolCollapsible";
+import type { ToolStatus } from "./utils";
+
+export const ReadSkillTool: React.FC<{
+ label: string;
+ body: string;
+ status: ToolStatus;
+ isError: boolean;
+ errorMessage?: string;
+}> = ({ label, body, status, isError, errorMessage }) => {
+ const hasContent = body.length > 0;
+ const isRunning = status === "running";
+
+ return (
+
+
+
+ {isRunning ? `Reading ${label}…` : `Read ${label}`}
+
+ {isError && (
+
+
+
+
+
+ {errorMessage || "Failed to read skill"}
+
+
+ )}
+ {isRunning && (
+
+ )}
+ >
+ }
+ >
+ {body && (
+
+
+ {body}
+
+
+ )}
+
+ );
+};
diff --git a/site/src/pages/AgentsPage/components/ChatElements/tools/Tool.stories.tsx b/site/src/pages/AgentsPage/components/ChatElements/tools/Tool.stories.tsx
index ca782edc12..42cd297038 100644
--- a/site/src/pages/AgentsPage/components/ChatElements/tools/Tool.stories.tsx
+++ b/site/src/pages/AgentsPage/components/ChatElements/tools/Tool.stories.tsx
@@ -1342,6 +1342,12 @@ export const ReadSkillCompleted: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
expect(canvas.getByText(/Read skill deep-review/)).toBeInTheDocument();
+ // Expand the collapsible to verify markdown body renders.
+ const toggle = canvas.getByRole("button");
+ await userEvent.click(toggle);
+ await waitFor(() => {
+ expect(canvas.getByText("Deep Review Skill")).toBeInTheDocument();
+ });
},
};
@@ -1393,6 +1399,12 @@ export const ReadSkillFileCompleted: Story = {
expect(
canvas.getByText(/Read deep-review\/roles\/security-reviewer\.md/),
).toBeInTheDocument();
+ // Expand the collapsible to verify markdown content renders.
+ const toggle = canvas.getByRole("button");
+ await userEvent.click(toggle);
+ await waitFor(() => {
+ expect(canvas.getByText("Security Reviewer Role")).toBeInTheDocument();
+ });
},
};
diff --git a/site/src/pages/AgentsPage/components/ChatElements/tools/Tool.tsx b/site/src/pages/AgentsPage/components/ChatElements/tools/Tool.tsx
index 084f00e8b5..e085aa6073 100644
--- a/site/src/pages/AgentsPage/components/ChatElements/tools/Tool.tsx
+++ b/site/src/pages/AgentsPage/components/ChatElements/tools/Tool.tsx
@@ -23,6 +23,7 @@ import { ListTemplatesTool } from "./ListTemplatesTool";
import { ProcessOutputTool } from "./ProcessOutputTool";
import { ProposePlanTool } from "./ProposePlanTool";
import { ReadFileTool } from "./ReadFileTool";
+import { ReadSkillTool } from "./ReadSkillTool";
import { ReadTemplateTool } from "./ReadTemplateTool";
import { SubagentTool } from "./SubagentTool";
import { ToolCollapsible } from "./ToolCollapsible";
@@ -210,6 +211,55 @@ const ReadFileRenderer: FC = ({
);
};
+const ReadSkillRenderer: FC = ({
+ status,
+ args,
+ result,
+ isError,
+}) => {
+ const parsedArgs = parseArgs(args);
+ const skillName = parsedArgs ? asString(parsedArgs.name) : "";
+ const rec = asRecord(result);
+ const body = rec ? asString(rec.body) : "";
+
+ return (
+
+ );
+};
+
+const ReadSkillFileRenderer: FC = ({
+ status,
+ args,
+ result,
+ isError,
+}) => {
+ const parsedArgs = parseArgs(args);
+ const skillName = parsedArgs ? asString(parsedArgs.name) : "";
+ const filePath = parsedArgs ? asString(parsedArgs.path) : "";
+ const label =
+ skillName && filePath
+ ? `${skillName}/${filePath}`
+ : skillName || filePath || "skill file";
+ const rec = asRecord(result);
+ const content = rec ? asString(rec.content) : "";
+
+ return (
+
+ );
+};
+
const WriteFileRenderer: FC = ({
status,
args,
@@ -667,6 +717,8 @@ const toolRenderers: Record> = {
create_workspace: CreateWorkspaceRenderer,
list_templates: ListTemplatesRenderer,
read_template: ReadTemplateRenderer,
+ read_skill: ReadSkillRenderer,
+ read_skill_file: ReadSkillFileRenderer,
spawn_agent: SubagentRenderer,
wait_agent: SubagentRenderer,
message_agent: SubagentRenderer,