Skip to content
edmi-ui

Agent

Agent configuration card: model, instructions, tools and output schema.

StackBlitz ↗StackBlitz ↗StackBlitz ↗
Keeper agentclaude-opus
Instructions
Keep every index within its drift limit. Never trade without approval when the order is above $500.
Tools · 3

{ "index": string, "maxSlippage"?: number }

Output schema
{ status: "ok" | "skipped"; tx?: string }
Keeper agent
claude-opus
Instructions
Keep every index within its drift limit. Never trade without approval when the order is above $500.
Tools · 3

{ "index": string, "maxSlippage"?: number }

Output schema
{ status: "ok" | "skipped"; tx?: string }
Keeper agent claude-opus
Instructions
Keep every index within its drift limit. Never trade without approval when the order is above $500.
Tools · 0
{ "index": string, "maxSlippage"?: number }
Output schema
{ status: "ok" | "skipped"; tx?: string }

Built on card, accordion, badge and ai-code-block.

Terminal window
npx shadcn@latest add @edmi-ui/ai-agent
Terminal window
pnpm dlx shadcn@latest add @edmi-ui/ai-agent
Terminal window
yarn dlx shadcn@latest add @edmi-ui/ai-agent
Terminal window
bunx shadcn@latest add @edmi-ui/ai-agent

Pick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.

Terminal window
npx shadcn-vue@latest add @edmi-ui/ai-agent
Terminal window
pnpm dlx shadcn-vue@latest add @edmi-ui/ai-agent
Terminal window
yarn dlx shadcn-vue@latest add @edmi-ui/ai-agent
Terminal window
bunx shadcn-vue@latest add @edmi-ui/ai-agent

Pick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.

Terminal window
npx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/ai-agent.json
Terminal window
pnpm dlx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/ai-agent.json
Terminal window
yarn dlx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/ai-agent.json
Terminal window
bunx --bun shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/ai-agent.json

Pick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.

import {
Agent,
AgentContent,
AgentHeader,
AgentInstructions,
AgentOutput,
AgentTool,
AgentTools,
} from "@/components/ai/agent";
<Agent className="max-w-lg">
<AgentHeader name="Keeper agent" model="claude-opus" />
<AgentContent>
<AgentInstructions>
Keep every index within its drift limit. Never trade without approval
when the order is above <b>$500</b>.
</AgentInstructions>
<AgentTools>
<AgentTool name="get_prices" value="get_prices" />
<AgentTool name="rebalance" value="rebalance" />
<AgentTool name="post_feed" value="post_feed" />
</AgentTools>
<AgentOutput schema={`{ status: "ok" | "skipped"; tx?: string }`} />
</AgentContent>
</Agent>
<script setup lang="ts">
import {
Agent,
AgentContent,
AgentHeader,
AgentInstructions,
AgentOutput,
AgentTool,
AgentTools,
} from "@/components/ai/agent";
</script>
<template>
<Agent class="max-w-lg">
<AgentHeader name="Keeper agent" model="claude-opus" />
<AgentContent>
<AgentInstructions>
Keep every index within its drift limit. Never trade without approval when the order is above <b>$500</b>.
</AgentInstructions>
<AgentTools default-value="rebalance">
<AgentTool name="get_prices" value="get_prices" />
<AgentTool name="rebalance" value="rebalance" />
<AgentTool name="post_feed" value="post_feed" />
</AgentTools>
<AgentOutput />
</AgentContent>
</Agent>
</template>
<script lang="ts">
import {
Agent,
AgentContent,
AgentHeader,
AgentInstructions,
AgentOutput,
AgentTool,
AgentTools,
} from "$lib/components/ai/agent";
</script>
<Agent class="max-w-lg">
<AgentHeader name="Keeper agent" model="claude-opus" />
<AgentContent>
<AgentInstructions>
Keep every index within its drift limit. Never trade without approval when the order is above <b
>$500</b
>.
</AgentInstructions>
<AgentTools value="rebalance">
<AgentTool name="get_prices" value="get_prices" />
<AgentTool name="rebalance" value="rebalance" />
<AgentTool name="post_feed" value="post_feed" />
</AgentTools>
<AgentOutput />
</AgentContent>
</Agent>
registry/components/ai/agent.tsx
"use client";
import { cn } from "cn";
import type { ComponentProps, ReactNode } from "react";
import { Children, memo } from "react";
import { SparkleIcon, GearIcon } from "@phosphor-icons/react";
import { CodeBlock } from "@/registry/edmi/components/ai/code-block";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/registry/edmi/ui/accordion";
import { Badge } from "@/registry/edmi/ui/badge";
import { Card } from "@/registry/edmi/ui/card";
// Section label (DESIGN §5b `.ai-lbl`): mono 11px caps.
const LABEL =
"font-mono text-[11px] font-medium tracking-[0.8px] text-muted-foreground uppercase";
export type AgentProps = ComponentProps<typeof Card>;
/** An agent's configuration at a glance. Built on the ui card; `elevation` ✦ is forwarded to the card. */
export const Agent = memo(({ className, ...props }: AgentProps) => (
<Card
data-slot="ai-agent"
className={cn("not-prose w-full gap-0 py-0", className)}
{...props}
/>
));
export type AgentHeaderProps = ComponentProps<"div"> & {
name: string;
model?: string;
};
export const AgentHeader = memo(
({ className, name, model, ...props }: AgentHeaderProps) => (
<div
data-slot="ai-agent-header"
className={cn(
"flex w-full items-center gap-2.5 border-b border-border px-4 py-3.5",
className,
)}
{...props}
>
<span className="inline-flex size-[30px] shrink-0 items-center justify-center rounded-full bg-brand-soft text-brand-text">
<SparkleIcon
className="size-4"
/>
</span>
<span className="text-sm font-semibold">{name}</span>
{model && (
<Badge className="h-5 font-mono text-[11px]" variant="secondary">
{model}
</Badge>
)}
</div>
),
);
export type AgentContentProps = ComponentProps<"div">;
export const AgentContent = memo(
({ className, ...props }: AgentContentProps) => (
<div className={cn("flex flex-col gap-4 p-4", className)} {...props} />
),
);
export type AgentInstructionsProps = Omit<ComponentProps<"div">, "children"> & {
children: ReactNode;
};
export const AgentInstructions = memo(
({ className, children, ...props }: AgentInstructionsProps) => (
<div className={cn("flex flex-col gap-1.5", className)} {...props}>
<span className={LABEL}>Instructions</span>
<div className="text-[13.5px] leading-[1.6] text-foreground-2">
{children}
</div>
</div>
),
);
export type AgentToolsProps = ComponentProps<typeof Accordion>;
export const AgentTools = memo(
({ className, children, ...props }: AgentToolsProps) => (
<div className="flex flex-col gap-1">
<span className={LABEL}>Tools · {Children.count(children)}</span>
<Accordion
className={cn("border-t border-border-2", className)}
{...props}
>
{children}
</Accordion>
</div>
),
);
export type AgentToolProps = ComponentProps<typeof AccordionItem> & {
tool: {
// Matches the AI SDK `Tool` shape (`description`, `inputSchema`) without requiring it;
// a string schema is shown as typescript, anything else as JSON.
description?: string;
inputSchema?: unknown;
jsonSchema?: unknown;
};
/** ✦ Tool name shown in mono before the description; falls back to `value`. */
name?: string;
};
export const AgentTool = memo(
({ className, tool, value, name, ...props }: AgentToolProps) => {
const schema =
"jsonSchema" in tool && tool.jsonSchema
? tool.jsonSchema
: tool.inputSchema;
return (
<AccordionItem
className={cn("border-t-0 border-b border-border-2", className)}
value={value}
{...props}
>
<AccordionTrigger className="gap-2 py-[9px] text-[13px] font-normal">
<GearIcon
className="size-3.5 shrink-0 text-muted-foreground"
/>
<span className="font-mono text-[12.5px]">
{name ?? String(value ?? "")}
</span>
<span className="min-w-0 flex-1 truncate text-[13px] font-normal text-muted-foreground">
{tool.description ?? "No description"}
</span>
</AccordionTrigger>
<AccordionContent className="pb-2.5">
<CodeBlock
className="rounded-lg border-0 bg-muted"
code={
typeof schema === "string"
? schema
: JSON.stringify(schema, null, 2)
}
language={typeof schema === "string" ? "typescript" : "json"}
/>
</AccordionContent>
</AccordionItem>
);
},
);
export type AgentOutputProps = ComponentProps<"div"> & {
schema: string;
};
export const AgentOutput = memo(
({ className, schema, ...props }: AgentOutputProps) => (
<div className={cn("flex flex-col gap-1.5", className)} {...props}>
<span className={LABEL}>Output schema</span>
<CodeBlock
className="rounded-lg border-0 bg-muted"
code={schema}
language="typescript"
/>
</div>
),
);
Agent.displayName = "Agent";
AgentHeader.displayName = "AgentHeader";
AgentContent.displayName = "AgentContent";
AgentInstructions.displayName = "AgentInstructions";
AgentTools.displayName = "AgentTools";
AgentTool.displayName = "AgentTool";
AgentOutput.displayName = "AgentOutput";
registry/components/ai/agent/Agent.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { cn } from "@/registry/edmi/lib/utils"
import { Card } from "@/registry/edmi/ui/card"
import type { Elevation } from "@/registry/edmi/ui/elevation"
// An agent's configuration at a glance. Built on the ui card; `elevation` ✦ is forwarded to the card.
const props = withDefaults(defineProps<{
class?: HTMLAttributes["class"]
/** ✦ depth: sunken -1, flat 0, raised +1, floating +2. */
elevation?: Elevation
}>(), {
elevation: undefined,
})
</script>
<template>
<Card
data-slot="ai-agent"
:elevation="props.elevation"
:class="cn('not-prose w-full gap-0 py-0', props.class)"
>
<slot />
</Card>
</template>
registry/components/ai/agent/AgentContent.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { cn } from "@/registry/edmi/lib/utils"
const props = defineProps<{
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<div :class="cn('flex flex-col gap-4 p-4', props.class)">
<slot />
</div>
</template>
registry/components/ai/agent/AgentHeader.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { SparklesIcon } from "@lucide/vue"
import { cn } from "@/registry/edmi/lib/utils"
import { Badge } from "@/registry/edmi/ui/badge"
const props = defineProps<{
name: string
model?: string
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<div
data-slot="ai-agent-header"
:class="cn('flex w-full items-center gap-2.5 border-b border-border px-4 py-3.5', props.class)"
>
<span class="inline-flex size-[30px] shrink-0 items-center justify-center rounded-full bg-brand-soft text-brand-text">
<SparklesIcon class="size-4" />
</span>
<span class="text-sm font-semibold">{{ props.name }}</span>
<Badge v-if="props.model" class="h-5 font-mono text-[11px]" variant="secondary">
{{ props.model }}
</Badge>
</div>
</template>
registry/components/ai/agent/AgentInstructions.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { cn } from "@/registry/edmi/lib/utils"
const props = defineProps<{
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<div :class="cn('flex flex-col gap-1.5', props.class)">
<span class="font-mono text-[11px] font-medium tracking-[0.8px] text-muted-foreground uppercase">Instructions</span>
<div class="text-[13.5px] leading-[1.6] text-foreground-2">
<slot />
</div>
</div>
</template>
registry/components/ai/agent/AgentOutput.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { cn } from "@/registry/edmi/lib/utils"
import { CodeBlock } from "@/registry/edmi/components/ai/code-block"
const props = defineProps<{
schema: string
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<div :class="cn('flex flex-col gap-1.5', props.class)">
<span class="font-mono text-[11px] font-medium tracking-[0.8px] text-muted-foreground uppercase">Output schema</span>
<CodeBlock class="rounded-lg border-0 bg-muted" :code="props.schema" language="typescript" />
</div>
</template>
registry/components/ai/agent/AgentTool.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { Settings } from "@lucide/vue"
import { computed } from "vue"
import { cn } from "@/registry/edmi/lib/utils"
import { AccordionContent, AccordionItem, AccordionTrigger } from "@/registry/edmi/ui/accordion"
import { CodeBlock } from "@/registry/edmi/components/ai/code-block"
const props = defineProps<{
/** Matches the AI SDK `Tool` shape (`description`, `inputSchema`); a string schema is shown as typescript, anything else as JSON. */
tool: { description?: string, inputSchema?: unknown, jsonSchema?: unknown }
value: string
/** ✦ Tool name shown in mono before the description; falls back to `value`. */
name?: string
class?: HTMLAttributes["class"]
}>()
const schema = computed(() =>
"jsonSchema" in props.tool && props.tool.jsonSchema ? props.tool.jsonSchema : props.tool.inputSchema,
)
const isString = computed(() => typeof schema.value === "string")
const code = computed(() => (isString.value ? (schema.value as string) : JSON.stringify(schema.value, null, 2)))
</script>
<template>
<AccordionItem
:value="props.value"
:class="cn('border-t-0 border-b border-border-2', props.class)"
>
<AccordionTrigger class="gap-2 py-[9px] text-[13px] font-normal">
<Settings class="size-3.5 shrink-0 text-muted-foreground" />
<span class="font-mono text-[12.5px]">{{ props.name ?? props.value }}</span>
<span class="min-w-0 flex-1 truncate text-[13px] font-normal text-muted-foreground">
{{ props.tool.description ?? "No description" }}
</span>
</AccordionTrigger>
<AccordionContent class="pb-2.5">
<CodeBlock
class="rounded-lg border-0 bg-muted"
:code="code"
:language="isString ? 'typescript' : 'json'"
/>
</AccordionContent>
</AccordionItem>
</template>
registry/components/ai/agent/AgentTools.vue
<script setup lang="ts">
import type { AccordionRootEmits, AccordionRootProps } from "reka-ui"
import type { HTMLAttributes, VNode } from "vue"
import { reactiveOmit } from "@vueuse/core"
import { useForwardPropsEmits } from "reka-ui"
import { Comment, Fragment, useSlots } from "vue"
import { cn } from "@/registry/edmi/lib/utils"
import { Accordion } from "@/registry/edmi/ui/accordion"
// Reka needs `type`; single + collapsible matches the React port (Base UI default).
const props = withDefaults(
defineProps<AccordionRootProps & { class?: HTMLAttributes["class"] }>(),
{ type: "single", collapsible: true },
)
const emits = defineEmits<AccordionRootEmits>()
const delegatedProps = reactiveOmit(props, "class")
const forwarded = useForwardPropsEmits(delegatedProps, emits)
const slots = useSlots()
// Number of AgentTool children (looks through v-for fragments); called from the template, never at setup.
function toolCount() {
const walk = (nodes: VNode[]): number =>
nodes.reduce((n, node) => {
if (node.type === Fragment) {
return n + walk(Array.isArray(node.children) ? (node.children as VNode[]) : [])
}
return typeof node.type === "symbol" && (node.type as symbol) === (Comment as unknown as symbol) ? n : n + 1
}, 0)
return walk(slots.default?.() ?? [])
}
</script>
<template>
<div class="flex flex-col gap-1">
<span class="font-mono text-[11px] font-medium tracking-[0.8px] text-muted-foreground uppercase">Tools · {{ toolCount() }}</span>
<Accordion v-bind="forwarded" :class="cn('border-t border-border-2', props.class)">
<slot />
</Accordion>
</div>
</template>
registry/components/ai/agent/index.ts
export { default as Agent } from "./Agent.vue";
export { default as AgentContent } from "./AgentContent.vue";
export { default as AgentHeader } from "./AgentHeader.vue";
export { default as AgentInstructions } from "./AgentInstructions.vue";
export { default as AgentOutput } from "./AgentOutput.vue";
export { default as AgentTool } from "./AgentTool.vue";
export { default as AgentTools } from "./AgentTools.vue";
src/lib/registry/ai/agent/agent-content.svelte
<script lang="ts">
import { cn } from "$lib/utils.js";
import type { Snippet } from "svelte";
import type { HTMLAttributes } from "svelte/elements";
let {
class: className,
children,
...restProps
}: HTMLAttributes<HTMLDivElement> & { children?: Snippet } = $props();
</script>
<div class={cn("flex flex-col gap-4 p-4", className)} {...restProps}>
{@render children?.()}
</div>
src/lib/registry/ai/agent/agent-header.svelte
<script lang="ts">
import SparkleIcon from "phosphor-svelte/lib/Sparkle";
import { Badge } from "$lib/registry/ui/badge/index.js";
import { cn } from "$lib/utils.js";
import type { HTMLAttributes } from "svelte/elements";
let {
name,
model,
class: className,
...restProps
}: HTMLAttributes<HTMLDivElement> & { name: string; model?: string } = $props();
</script>
<div
data-slot="ai-agent-header"
class={cn("flex w-full items-center gap-2.5 border-b border-border px-4 py-3.5", className)}
{...restProps}
>
<span
class="inline-flex size-[30px] shrink-0 items-center justify-center rounded-full bg-brand-soft text-brand-text"
>
<SparkleIcon
class="size-4"
/>
</span>
<span class="text-sm font-semibold">{name}</span>
{#if model}
<Badge class="h-5 font-mono text-[11px]" variant="secondary">{model}</Badge>
{/if}
</div>
src/lib/registry/ai/agent/agent-instructions.svelte
<script lang="ts">
import { cn } from "$lib/utils.js";
import type { Snippet } from "svelte";
import type { HTMLAttributes } from "svelte/elements";
let {
class: className,
children,
...restProps
}: HTMLAttributes<HTMLDivElement> & { children?: Snippet } = $props();
</script>
<div class={cn("flex flex-col gap-1.5", className)} {...restProps}>
<span class="font-mono text-[11px] font-medium tracking-[0.8px] text-muted-foreground uppercase"
>Instructions</span
>
<div class="text-[13.5px] leading-[1.6] text-foreground-2">
{@render children?.()}
</div>
</div>
src/lib/registry/ai/agent/agent-output.svelte
<script lang="ts">
import { cn } from "$lib/utils.js";
import type { HTMLAttributes } from "svelte/elements";
import { CodeBlock } from "../code-block/index.js";
let {
schema,
class: className,
...restProps
}: HTMLAttributes<HTMLDivElement> & { schema: string } = $props();
</script>
<div class={cn("flex flex-col gap-1.5", className)} {...restProps}>
<span class="font-mono text-[11px] font-medium tracking-[0.8px] text-muted-foreground uppercase"
>Output schema</span
>
<CodeBlock class="rounded-lg border-0 bg-muted" code={schema} language="typescript" />
</div>
src/lib/registry/ai/agent/agent-tool.svelte
<script lang="ts">
import GearIcon from "phosphor-svelte/lib/Gear";
import {
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "$lib/registry/ui/accordion/index.js";
import { cn } from "$lib/utils.js";
import { CodeBlock } from "../code-block/index.js";
import { useAgentToolsContext } from "./use-agent.svelte.js";
let {
tool,
value,
name,
class: className,
}: {
/** Matches the AI SDK `Tool` shape (`description`, `inputSchema`); a string schema is shown as typescript, anything else as JSON. */
tool: { description?: string; inputSchema?: unknown; jsonSchema?: unknown };
value: string;
/** ✦ Tool name shown in mono before the description; falls back to `value`. */
name?: string;
class?: string;
} = $props();
const tools = useAgentToolsContext();
$effect(() => tools?.register());
const schema = $derived(
"jsonSchema" in tool && tool.jsonSchema ? tool.jsonSchema : tool.inputSchema
);
const isString = $derived(typeof schema === "string");
const code = $derived(isString ? (schema as string) : JSON.stringify(schema, null, 2));
</script>
<AccordionItem {value} class={cn("border-t-0 border-b border-border-2", className)}>
<AccordionTrigger class="gap-2 py-[9px] text-[13px] font-normal">
<GearIcon
class="size-3.5 shrink-0 text-muted-foreground"
/>
<span class="font-mono text-[12.5px]">{name ?? value}</span>
<span class="min-w-0 flex-1 truncate text-[13px] font-normal text-muted-foreground">
{tool.description ?? "No description"}
</span>
</AccordionTrigger>
<AccordionContent class="pb-2.5">
<CodeBlock class="rounded-lg border-0 bg-muted" {code} language={isString ? "typescript" : "json"} />
</AccordionContent>
</AccordionItem>
src/lib/registry/ai/agent/agent-tools.svelte
<script lang="ts">
import { Accordion } from "$lib/registry/ui/accordion/index.js";
import { cn } from "$lib/utils.js";
import { type ComponentProps, untrack } from "svelte";
import { setAgentToolsContext } from "./use-agent.svelte.js";
// single + collapsible matches the React port (Base UI default).
let {
class: className,
children,
value = $bindable<string | undefined>(),
...restProps
}: Omit<ComponentProps<typeof Accordion>, "type" | "value"> & { value?: string } = $props();
let count = $state(0);
setAgentToolsContext({
register() {
// untrack: register runs inside the child's effect and must not subscribe to `count`.
untrack(() => {
count += 1;
});
return () => {
untrack(() => {
count -= 1;
});
};
},
});
</script>
<div class="flex flex-col gap-1">
<span class="font-mono text-[11px] font-medium tracking-[0.8px] text-muted-foreground uppercase"
>Tools · {count}</span
>
<Accordion
type="single"
bind:value
class={cn("border-t border-border-2", className)}
{...restProps as object}
>
{@render children?.()}
</Accordion>
</div>
src/lib/registry/ai/agent/agent.svelte
<script lang="ts">
import { Card } from "$lib/registry/ui/card/index.js";
import { cn } from "$lib/utils.js";
import type { ComponentProps } from "svelte";
// An agent's configuration at a glance. Built on the ui card; `elevation` ✦ is forwarded to the card (Card props).
let {
class: className,
children,
...restProps
}: ComponentProps<typeof Card> = $props();
</script>
<Card data-slot="ai-agent" class={cn("not-prose w-full gap-0 py-0", className)} {...restProps}>
{@render children?.()}
</Card>
src/lib/registry/ai/agent/use-agent.svelte.ts
import { getContext, setContext } from "svelte";
/** AgentTools counts its AgentTool children through this context ("Tools · 3"). */
export interface AgentToolsContextValue {
register: () => () => void;
}
const KEY = Symbol("ai-agent-tools");
export function setAgentToolsContext(value: AgentToolsContextValue) {
return setContext(KEY, value);
}
export function useAgentToolsContext(): AgentToolsContextValue | undefined {
return getContext<AgentToolsContextValue | undefined>(KEY);
}
src/lib/registry/ai/agent/index.ts
import Root from "./agent.svelte";
import Content from "./agent-content.svelte";
import Header from "./agent-header.svelte";
import Instructions from "./agent-instructions.svelte";
import Output from "./agent-output.svelte";
import Tool from "./agent-tool.svelte";
import Tools from "./agent-tools.svelte";
export {
Content as AgentContent,
Header as AgentHeader,
Instructions as AgentInstructions,
Output as AgentOutput,
Root as Agent,
Tool as AgentTool,
Tools as AgentTools,
};

See the Elevation guide for the levels, roles and layered mode.

The agent card are flat by default and take the surface level in layered mode (raised). sunken (-1) is a soft inset, raised (+1) a bevel and floating (+2) a bevel with a soft drop.

StackBlitz ↗StackBlitz ↗StackBlitz ↗

Sunken (-1)

Keeper agentclaude-opus
Instructions
Keep every index within its drift limit. Never trade without approval when the order is above $500.

Flat (0)

Keeper agentclaude-opus
Instructions
Keep every index within its drift limit. Never trade without approval when the order is above $500.

Raised (+1)

Keeper agentclaude-opus
Instructions
Keep every index within its drift limit. Never trade without approval when the order is above $500.

Floating (+2)

Keeper agentclaude-opus
Instructions
Keep every index within its drift limit. Never trade without approval when the order is above $500.

Sunken (-1)

Keeper agent
claude-opus
Instructions
Keep every index within its drift limit. Never trade without approval when the order is above $500.

Flat (0)

Keeper agent
claude-opus
Instructions
Keep every index within its drift limit. Never trade without approval when the order is above $500.

Raised (+1)

Keeper agent
claude-opus
Instructions
Keep every index within its drift limit. Never trade without approval when the order is above $500.

Floating (+2)

Keeper agent
claude-opus
Instructions
Keep every index within its drift limit. Never trade without approval when the order is above $500.

Sunken (-1)

Keeper agent claude-opus
Instructions
Keep every index within its drift limit. Never trade without approval when the order is above $500.

Flat (0)

Keeper agent claude-opus
Instructions
Keep every index within its drift limit. Never trade without approval when the order is above $500.

Raised (+1)

Keeper agent claude-opus
Instructions
Keep every index within its drift limit. Never trade without approval when the order is above $500.

Floating (+2)

Keeper agent claude-opus
Instructions
Keep every index within its drift limit. Never trade without approval when the order is above $500.
Part Prop Type Default
Agent elevation "auto" | "sunken" | "flat" | "raised" | "floating" "auto"
AgentHeader name, model string, string
AgentInstructions children ReactNode
AgentTools Accordion props (multiple, defaultValue)
AgentTool tool, value { description?, inputSchema?, jsonSchema? }, string
AgentOutput schema string
  • elevation: depth of the card (forwarded to the Card).
  • AgentTool name: tool name shown in mono before the description (falls back to value).
  • A string inputSchema is shown as TypeScript; anything else as JSON.
  • Vue and Svelte: AgentTools takes the Reka / Bits accordion props (type defaults to single, collapsible), and the tool count in the label is derived from its AgentTool children.