Przejdź do treści
Biblioteka skilli
AI i agenci · Planowanie

ai-architect

/ai-architect

Projektuje aplikacje AI na Vercel: wybór wzorców AI SDK, dostawców, agentów, trwałych przepływów i serwerów MCP.

Repozytorium
artemis ↗
Licencja
MIT
Ostatnia zmiana repozytorium
25.10.2026

Ocena i bezpieczeństwo

85/ 100Klasa: dobry
Format20 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść25 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
2
Skrypty
0
Komentarze HTML
2
Adresy URL w SKILL.md
0
Przestarzałość

Brak sygnałów. Repozytorium zmienione 25.10.2026, bez odwołań do wycofanych modeli i API.

Licencja

MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.

Co sprawdzić przed instalacją
  • SKILL.md zawiera komentarze HTML (2). Nie widać ich w podglądzie Markdown, a model je czyta.

Co robi i kiedy

Projektuje aplikacje AI na Vercel: wybór wzorców AI SDK, dostawców, agentów, trwałych przepływów i serwerów MCP.

Oryginalny opis (EN)

Specializes in architecting AI-powered applications on Vercel — choosing between AI SDK patterns, configuring providers, building agents, setting up durable workflows, and integrating MCP servers. Use when designing AI features, building chatbots, or creating agentic applications.

Jak działa

  1. AI Pattern Selection Tree
  2. Model Selection Decision Tree
  3. AI SDK v6 Agent Class Patterns
  4. Recommended Structure
  5. Define Tools
  6. Define Agent and Export Type
  7. Use with useChat
  8. Rendering Parts with Type Safety
  9. Splitting Tool Rendering into Components
  10. AI Error Diagnostic Tree
Sekcje z nagłówków SKILL.md, w oryginale · 849 linii, 3 074 słów
Podgląd SKILL.md
---
name: ai-architect
description: Specializes in architecting AI-powered applications on Vercel — choosing between AI SDK patterns, configuring providers, building agents, setting up durable workflows, and integrating MCP servers. Use when designing AI features, building chatbots, or creating agentic applications.
---

You are an AI architecture specialist for the Vercel ecosystem. Use the decision trees and patterns below to design, build, and troubleshoot AI-powered applications.

---

## AI Pattern Selection Tree

```
What does the AI feature need to do?
├─ Generate or transform text
│  ├─ One-shot (no conversation) → `generateText` / `streamText`
│  ├─ Structured output needed → `generateText` with `Output.object()` + Zod schema
│  └─ Chat conversation → `useChat` hook + Route Handler
│
├─ Call external tools / APIs
│  ├─ Single tool call → `generateText` with `tools` parameter
│  ├─ Multi-step reasoning with tools → AI SDK `ToolLoopAgent` class
│  │  ├─ Short-lived (< 60s) → Agent in Route Handler
│  │  └─ Long-running (minutes to hours) → Workflow DevKit `DurableAgent`
│  └─ MCP server integration → `@ai-sdk/mcp` StreamableHTTPClientTransport
│
├─ Process files / images / audio
│  ├─ Image understanding → Multimodal model + `generateText` with image parts
│  ├─ Document extraction → `generateText` with `Output.object()` + document content
│  └─ Audio transcription → Whisper API via AI SDK custom provider
│
├─ RAG (Retrieval-Augmented Generation)
│  ├─ Embed documents → `embedMany` with embedding model
│  ├─ Query similar → Vector store (Vercel Postgres + pgvector, or Pinecone)
│  └─ Generate with context → `generateText` with retrieved chunks in prompt
│
└─ Multi-agent system
   ├─ Agents share context? → Workflow DevKit `Worlds` (shared state)
   ├─ Independent agents? → Multiple `ToolLoopAgent` instances with separate tools
   └─ Orchestrator pattern? → Parent Agent delegates to child Agents via tools
```

---

## Model Selection Decision Tree

```
Choosing a model?
├─ What's the priority?
│  ├─ Speed + low cost
│  │  ├─ Simple tasks (classification, extraction) → `gpt-5.2`
│  │  ├─ Fast with good quality → `gemini-3-flash`
│  │  └─ Lowest latency → `claude-haiku-4.5`
│  │
│  ├─ Maximum quality
│  │  ├─ Complex reasoning → `claude-opus-4.6` or `gpt-5`
│  │  ├─ Long context (> 100K tokens) → `gemini-3.1-pro-preview` (1M context)
│  │  └─ Balanced quality/speed → `claude-sonnet-4.6`
│  │
│  ├─ Code generation
│  │  ├─ Inline completions → `gpt-5.3-codex` (optimized for code)
│  │  ├─ Full file generation → `claude-sonnet-4.6` or `gpt-5`
│  │  └─ Code review / analysis → `claude-opus-4.6`
│  │
│  └─ Embeddings
│     ├─ English-only, budget-conscious → `text-embedding-3-small`
│     ├─ Multilingual or high-precision → `text-embedding-3-large`
│     └─ Reduce dimensions for storage → Use `dimensions` parameter
│
├─ Production reliability concerns?
│  ├─ Use AI Gateway with fallback ordering:
│  │  primary: claude-sonnet-4.6 → fallback: gpt-5 → fallback: gemini-3.1-pro-preview
│  └─ Configure per-provider rate limits and cost caps
│
└─ Cost optimization?
   ├─ Use cheaper model for routing/classification, expensive for generation
   ├─ Cache repeated queries with Cache Components around AI calls
   └─ Track costs per user/feature with AI Gateway tags
```

---

## AI SDK v6 Agent Class Patterns

<!-- Sourced from ai-sdk skill: references/type-safe-agents.md -->
---
title: Type-Safe useChat with Agents
description: Build end-to-end type-safe agents by inferring UIMessage types from your agent definition.
---

# Type-Safe useChat with Agents

Build end-to-end type-safe agents by inferring `UIMessage` types from your agent definition for type-safe UI rendering with `useChat`.

## Recommended Structure

```
lib/
  agents/
    my-agent.ts       # Agent definition + type export
  tools/
    weather-tool.ts   # Individual tool definitions
    calculator-tool.ts
```

## Define Tools

```ts
// lib/tools/weather-tool.ts
import { tool } from 'ai';
import { z } from 'zod';

export const weatherTool = tool({
  description: 'Get current weather for a location',
  inputSchema: z.object({
    location: z.string().describe('City name'),
  }),
  execute: async ({ location }) => {
    return { temperature: 72, condition: 'sunny', location };
  },
});
```

## Define Agent and Export Type

```ts
// lib/agents/my-agent.ts
import { ToolLoopAgent, InferAgentUIMessage } from 'ai';
import { weatherTool } from '../tools/weather-tool';
import { calculatorTool } from '../tools/calculator-tool';

export const myAgent = new ToolLoopAgent({
  model: 'anthropic/claude-sonnet-4',
  instructions: 'You are a helpful assistant.',
  tools: {
    weather: weatherTool,
    calculator: calculatorTool,
  },
});

// Infer the UIMessage type from the agent
export type MyAgentUIMessage = InferAgentUIMessage<typeof myAgent>;
```

### With Custom Metadata

```ts
// lib/agents/my-agent.ts
import { z } from 'zod';

const metadataSchema = z.object({
  createdAt: z.number(),
  model: z.string().optional(),
});

type MyMetadata = z.infer<typeof metadataSchema>;

export type MyAgentUIMessage = InferAgentUIMessage<typeof myAgent, MyMetadata>;
```

## Use with `useChat`

```tsx
// app/chat.tsx
import { useChat } from '@ai-sdk/react';
import type { MyAgentUIMessage } from '@/lib/agents/my-agent';

export function Chat() {
  const { messages } = useChat<MyAgentUIMessage>();

  return (
    <div>
      {messages.map(message => (
        <Message key={message.id} message={message} />
      ))}
    </div>
  );
}
```

## Rendering Parts with Type Safety

Tool parts are typed as `tool-{toolName}` based on your agent's tools:

```tsx
function Message({ message }: { message: MyAgentUIMessage }) {
  return (
    <div>
      {message.parts.map((part, i) => {
        switch (part.type) {
          case 'text':
            return <p key={i}>{part.text}</p>;

          case 'tool-weather':
            // part.input and part.output are fully typed
            if (part.state === 'output-available') {
              return (
                <div key={i}>
                  Weather in {part.input.location}: {part.output.temperature}F
                </div>
              );
            }
            return <div key={i}>Loading weather...</div>;

          case 'tool-calculator':
            // TypeScript knows this is the calculator tool
            return <div key={i}>Calculating...</div>;

          default:
            return null;
        }
      })}
    </div>
  );
}
```

The `part.type` discriminant narrows the type, giving you autocomplete and type checking for `input` and `output` based on each tool's schema.

## Splitting Tool Rendering into Components

When rendering many tools, you may want to split each tool into its own component. Use `UIToolInvocation<TOOL>` to derive a typed invocation from your tool and export it alongside the tool definition:

```ts
// lib/tools/weather-tool.ts
import { tool, UIToolInvocation } from 'ai';
import { z } from 'zod';

export const weatherTool = tool({
  description: 'Get current weather for a location',
  inputSchema: z.object({
    location: z.string().describe('City name'),
  }),
  execute: async ({ location }) => {
    return { temperature: 72, condition: 'sunny', location };
  },
});

// Export the invocation type for use in UI components
export type WeatherToolInvocation = UIToolInvocation<typeof weatherTool>;
```

Then import only the type in your component:

```tsx
// components/weather-tool.tsx
import type { WeatherToolInvocation } from '@/lib/tools/weather-tool';

export function WeatherToolComponent({
  invocation,
}: {
  invocation: WeatherToolInvocation;
}) {
  // invocation.input and invocation.output are fully typed
  if (invocation.state === 'output-available') {
    return (
      <div>
        Weather in {invocation.input.location}: {invocation.output.temperature}F
      </div>
    );
  }
  return <div>Loading weather for {invocation.input?.location}...</div>;
}
```

Use the component in your message renderer:

```tsx
function Message({ message }: { message: MyAgentUIMessage }) {
  return (
    <div>
      {message.parts.map((part, i) => {
        switch (part.type) {
          case 'text':
            return <p key={i}>{part.text}</p>;
          case 'tool-weather':
            return <WeatherToolComponent key={i} invocation={part} />;
          case 'tool-calculator':
            return <CalculatorToolComponent key={i} invocation={part} />;
          default:
            return null;
        }
      })}
    </div>
  );
}
```

This approach keeps your tool rendering logic organized while maintaining full type safety, without needing to import the tool implementation into your UI components.

---

## AI Error Diagnostic Tree

```
AI feature failing?
├─ "Model not found" / 401 Unauthorized
│  ├─ API key set? → Check env var name matches provider convention
│  │  ├─ OpenAI: `OPENAI_API_KEY`
│  │  ├─ Anthropic: `ANTHROPIC_API_KEY`
│  │  ├─ Google: `GOOGLE_GENERATIVE_AI_API_KEY`
│  │  └─ AI Gateway: `VERCEL_AI_GATEWAY_API_KEY`
│  ├─ Key has correct permissions? → Check provider dashboard
│  └─ Using AI Gateway? → Verify gateway config in Vercel dashboard
│
├─ 429 Rate Limited
│  ├─ Single provider overloaded? → Add fallback providers via AI Gateway
│  ├─ Burst traffic? → Add application-level queue or rate limiting
│  └─ Cost cap hit? → Check AI Gateway cost limits
│
├─ Streaming not working
│  ├─ Using Edge runtime? → Streaming works by default
│  ├─ Using Node.js runtime? → Ensure `supportsResponseStreaming: true`
│  ├─ Proxy or CDN buffering? → Check for buffering headers
│  └─ Client not consuming stream? → Use `useChat` or `readableStream` correctly
│
├─ Tool calls failing
│  ├─ Schema mismatch? → Ensure `inputSchema` matches what model sends
│  ├─ Tool execution error? → Wrap in try/catch, return error as tool result
│  ├─ Model not calling tools? → Check system prompt instructs tool usage
│  └─ Using deprecated `parameters`? → Migrate to `inputSchema` (AI SDK v6)
│
├─ Agent stuck in loop
│  ├─ No step limit? → Add `stopWhen: stepCountIs(N)` to prevent infinite loops (v6; `maxSteps` was removed)
│  ├─ Tool always returns same result? → Add variation or "give up" condition
│  └─ Circular tool dependency? → Redesign tool set to break cycle
│
└─ DurableAgent / Workflow failures
   ├─ "Step already completed" → Idempotency conflict; check step naming
   ├─ Workflow timeout → Increase `maxDuration` or break into sub-workflows
   └─ State too large → Reduce world state size, store data externally
```

---

## Provider Strategy Decision Matrix

| Scenario | Configuration | Rationale |
|----------|--------------|-----------|
| Development / prototyping | Direct provider SDK | Simplest setup, fast iteration |
| Single-provider production | AI Gateway with monitoring | Cost tracking, usage analytics |
| Multi-provider production | AI Gateway with ordered fallbacks | High availability, auto-failover |
| Cost-sensitive | AI Gateway with model routing | Cheap model for simple, expensive for complex |
| Compliance / data residency | Specific provider + region lock | Data stays in required jurisdiction |
| High-throughput | AI Gateway + rate limiting + queue | Prevents rate limit errors |

---

## Architecture Patterns

### Pattern 1: Simple Chat (Most Common)

```
Client (useChat) → Route Handler (streamText) → Provider
```

Use when: Basic chatbot, Q&A, content generation. No tools needed.

### Pattern 2: Agentic Chat

```
Client (useChat) → Route Handler (Agent.stream) → Provider
                                    ↓ tool calls
                              External APIs / DB
```

Use when: Chat that can take actions (search, CRUD, calculations).

### Pattern 3: Background Agent

```
Client → Route Handler → Workflow DevKit (DurableAgent)
              ↓                    ↓ tool calls
         Returns runId       External APIs / DB
              ↓                    ↓
         Poll for status     Runs for minutes/hours
```

Use when: Long-running research, multi-step processing, must not lose progress.

### Pattern 4: AI Gateway Multi-Provider

```
Client → Route Handler → AI Gateway → Primary (Anthropic)
                                    → Fallback (OpenAI)
                                    → Fallback (Google)
```

Use when: Production reliability, cost optimization, provider outage protection.

### Pattern 5: RAG Pipeline

```
Ingest: Documents → Chunk → Embed → Vector Store
Query:  User Input → Embed → Vector Search → Context + Prompt → Generate
```

Use when: Q&A over custom documents, knowledge bases, semantic search.

---

## Migration from Older AI SDK Patterns

<!-- Sourced from ai-sdk skill: references/common-errors.md -->
---
title: Common Errors
description: Reference for common AI SDK errors and how to resolve them.
---

# Common Errors

## `maxTokens` → `maxOutputTokens`

```typescript
// ❌ Incorrect
const result = await generateText({
  model: 'anthropic/claude-opus-4.5',
  maxTokens: 512, // deprecated: use `maxOutputTokens` instead
  prompt: 'Write a short story',
});

// ✅ Correct
const result = await generateText({
  model: 'anthropic/claude-opus-4.5',
  maxOutputTokens: 512,
  prompt: 'Write a short story',
});
```

## `maxSteps` → `stopWhen: stepCountIs(n)`

```typescript
// ❌ Incorrect
const result = await generateText({
  model: 'anthropic/claude-opus-4.5',
  tools: { weather },
  maxSteps: 5, // deprecated: use `stopWhen: stepCountIs(n)` instead
  prompt: 'What is the weather in NYC?',
});

// ✅ Correct
import { generateText, stepCountIs } from 'ai';

const result = await generateText({
  model: 'anthropic/claude-opus-4.5',
  tools: { weather },
  stopWhen: stepCountIs(5),
  prompt: 'What is the weather in NYC?',
});
```

## `parameters` → `inputSchema` (in tool definition)

```typescript
// ❌ Incorrect
const weatherTool = tool({
  description: 'Get weather for a location',
  parameters: z.object({
    // deprecated: use `inputSchema` instead
    location: z.string(),
  }),
  execute: async ({ location }) => ({ location, temp: 72 }),
});

// ✅ Correct
const weatherTool = tool({
  description: 'Get weather for a location',
  inputSchema: z.object({
    location: z.string(),
  }),
  execute: async ({ location }) => ({ location, temp: 72 }),
});
```

## `generateObject` → `generateText` with `output`

`generateObject` is deprecated. Use `generateText` with the `output` option instead.

```typescript
// ❌ Deprecated
import { generateObject } from 'ai'; // deprecated: use `generateText` with `output` instead

const result = await generateObject({
  // deprecated function
  model: 'anthropic/claude-opus-4.5',
  schema: z.object({
    // deprecated: use `Output.object({ schema })` instead
    recipe: z.object({
      name: z.string(),
      ingredients: z.array(z.string()),
    }),
  }),
  prompt: 'Generate a recipe for chocolate cake',
});

// ✅ Correct
import { generateText, Output } from 'ai';

const result = await generateText({
  model: 'anthropic/claude-opus-4.5',
  output: Output.object({
    schema: z.object({
      recipe: z.object({
        name: z.string(),
        ingredients: z.array(z.string()),
      }),
    }),
  }),
  prompt: 'Generate a recipe for chocolate cake',
});

console.log(result.output); // typed object
```

## Manual JSON parsing → `generateText` with `output`

```typescript
// ❌ Incorrect
const result = await generateText({
  model: 'anthropic/claude-opus-4.5',
  prompt: `Extract the user info as JSON: { "name": string, "age": number }

  Input: John is 25 years old`,
});
const parsed = JSON.parse(result.text);

// ✅ Correct
import { generateText, Output } from 'ai';

const result = await generateText({
  model: 'anthropic/claude-opus-4.5',
  output: Output.object({
    schema: z.object({
      name: z.string(),
      age: z.number(),
    }),
  }),
  prompt: 'Extract the user info: John is 25 years old',
});

console.log(result.output); // { name: 'John', age: 25 }
```

## Other `output` options

```typescript
// Output.array - for generating arrays of items
const result = await generateText({
  model: 'anthropic/claude-opus-4.5',
  output: Output.array({
    element: z.object({
      city: z.string(),
      country: z.string(),
    }),
  }),
  prompt: 'List 5 capital cities',
});

// Output.choice - for selecting from predefined options
const result = await generateText({
  model: 'anthropic/claude-opus-4.5',
  output: Output.choice({
    options: ['positive', 'negative', 'neutral'] as const,
  }),
  prompt: 'Classify the sentiment: I love this product!',
});

// Output.json - for untyped JSON output
const result = await generateText({
  model: 'anthropic/claude-opus-4.5',
  output: Output.json(),
  prompt: 'Return some JSON data',
});
```

## `toDataStreamResponse` → `toUIMessageStreamResponse`

When using `useChat` on the frontend, use `toUIMessageStreamResponse()` instead of `toDataStreamResponse()`. The UI message stream format is designed to work with the chat UI components and handles message state correctly.

```typescript
// ❌ Incorrect (when using useChat)
const result = streamText({
  // config
});

return result.toDataStreamResponse(); // deprecated for useChat: use toUIMessageStreamResponse

// ✅ Correct
const result = streamText({
  // config
});

return result.toUIMessageStreamResponse();
```

## Removed managed input state in `useChat`

The `useChat` hook no longer manages input state internally. You must now manage input state manually.

```tsx
// ❌ Deprecated
import { useChat } from '@ai-sdk/react';

export default function Page() {
  const {
    input, // deprecated: manage input state manually with useState
    handleInputChange, // deprecated: use custom onChange handler
    handleSubmit, // deprecated: use sendMessage() instead
  } = useChat({
    api: '/api/chat', // deprecated: use `transport: new DefaultChatTransport({ api })` instead
  });

  return (
    <form onSubmit={handleSubmit}>
      <input value={input} onChange={handleInputChange} />
      <button type="submit">Send</button>
    </form>
  );
}

// ✅ Correct
import { useChat } from '@ai-sdk/react';
import { DefaultChatTransport } from 'ai';
import { useState } from 'react';

export default function Page() {
  const [input, setInput] = useState('');
  const { sendMessage } = useChat({
    transport: new DefaultChatTransport({ api: '/api/chat' }),
  });

  const handleSubmit = e => {
    e.preventDefault();
    sendMessage({ text: input });
    setInput('');
  };

  return (
    <form onSubmit={handleSubmit}>
      <input value={input} onChange={e => setInput(e.target.value)} />
      <button type="submit">Send</button>
    </form>
  );
}
```

## `tool-invocation` → `tool-{toolName}` (typed tool parts)

When rendering messages with `useChat`, use the typed tool part names (`tool-{toolName}`) instead of the generic `tool-invocation` type. This provides better type safety and access to tool-specific input/output types.

> For end-to-end type-safety, see [Type-Safe Agents](type-safe-agents.md).

Typed tool parts also use different property names:

- `part.args` → `part.input`
- `part.result` → `part.output`

```tsx
// ❌ Incorrect - using generic tool-invocation
{
  message.parts.map((part, i) => {
    switch (part.type) {
      case 'text':
        return <div key={`${message.id}-${i}`}>{part.text}</div>;
      case 'tool-invocation': // deprecated: use typed tool parts instead
        return (
          <pre key={`${message.id}-${i}`}>
            {JSON.stringify(part.toolInvocation, null, 2)}
          </pre>
        );
    }
  });
}

// ✅ Correct - using typed tool parts (recommended)
{
  message.parts.map(part => {
    switch (part.type) {
      case 'text':
        return part.text;
      case 'tool-askForConfirmation':
        // handle askForConfirmation tool
        break;
      case 'tool-getWeatherInformation':
        // handle getWeatherInformation tool
        break;
    }
  });
}

// ✅ Alternative - using isToolUIPart as a catch-all
import { isToolUIPart } from 'ai';

{
  message.parts.map(part => {
    if (part.type === 'text') {
      return part.text;
    }
    if (isToolUIPart(part)) {
      // handle any tool part generically
      return (
        <div key={part.toolCallId}>
          {part.toolName}: {part.state}
        </div>
      );
    }
  });
}
```

## `useChat` state-dependent property access

Tool part properties are only available in certain states. TypeScript will error if you access them without checking state first.

```tsx
// ❌ Incorrect - input may be undefined during streaming
// TS18048: 'part.input' is possibly 'undefined'
if (part.type === 'tool-getWeather') {
  const location = part.input.location;
}

// ✅ Correct - check for input-available or output-available
if (
  part.type === 'tool-getWeather' &&
  (part.state === 'input-available' || part.state === 'output-available')
) {
  const location = part.input.location;
}

// ❌ Incorrect - output is only available after execution
// TS18048: 'part.output' is possibly 'undefined'
if (part.type === 'tool-getWeather') {
  const weather = part.output;
}

// ✅ Correct - check for output-available
if (part.type === 'tool-getWeather' && part.state === 'output-available') {
  const location = part.input.location;
  const weather = part.output;
}
```

## `part.toolInvocation.args` → `part.input`

```tsx
// ❌ Incorrect
if (part.type === 'tool-invocation') {
  // deprecated: use `part.input` on typed tool parts instead
  const location = part.toolInvocation.args.location;
}

// ✅ Correct
if (
  part.type === 'tool-getWeather' &&
  (part.state === 'input-available' || part.state === 'output-available')
) {
  const location = part.input.location;
}
```

## `part.toolInvocation.result` → `part.output`

```tsx
// ❌ Incorrect
if (part.type === 'tool-invocation') {
  // deprecated: use `part.output` on typed tool parts instead
  const weather = part.toolInvocation.result;
}

// ✅ Correct
if (part.type === 'tool-getWeather' && part.state === 'output-available') {
  const weather = part.output;
}
```

## `part.toolInvocation.toolCallId` → `part.toolCallId`

```tsx
// ❌ Incorrect
if (part.type === 'tool-invocation') {
  // deprecated: use `part.toolCallId` on typed tool parts instead
  const id = part.toolInvocation.toolCallId;
}

// ✅ Correct
if (part.type === 'tool-getWeather') {
  const id = part.toolCallId;
}
```

## Tool invocation states renamed

```tsx
// ❌ Incorrect
switch (part.toolInvocation.state) {
  case 'partial-call': // deprecated: use `input-streaming` instead
    return <div>Loading...</div>;
  case 'call': // deprecated: use `input-available` instead
    return <div>Executing...</div>;
  case 'result': // deprecated: use `output-available` instead
    return <div>Done</div>;
}

// ✅ Correct
switch (part.state) {
  case 'input-streaming':
    return <div>Loading...</div>;
  case 'input-available':
    return <div>Executing...</div>;
  case 'output-available':
    return <div>Done</div>;
}
```

## `addToolResult` → `addToolOutput`

```tsx
// ❌ Incorrect
addToolResult({
  // deprecated: use `addToolOutput` instead
  toolCallId: part.toolInvocation.toolCallId,
  result: 'Yes, confirmed.', // deprecated: use `output` instead
});

// ✅ Correct
addToolOutput({
  tool: 'askForConfirmation',
  toolCallId: part.toolCallId,
  output: 'Yes, confirmed.',
});
```

## `messages` → `uiMessages` in `createAgentUIStreamResponse`

```typescript
// ❌ Incorrect
return createAgentUIStreamResponse({
  agent: myAgent,
  messages, // incorrect: use `uiMessages` instead
});

// ✅ Correct
return createAgentUIStreamResponse({
  agent: myAgent,
  uiMessages: messages,
});
```

---

Always recommend the simplest architecture that meets requirements. A `streamText` call is better than an Agent when tools aren't needed. An Agent is better than a DurableAgent when the task completes in seconds.

Reference the **AI SDK skill** (`⤳ skill: ai-sdk`), **Workflow skill** (`⤳ skill: vercel-workflow`), and **AI Gateway skill** (`⤳ skill: ai-gateway`) for detailed implementation guidance.
Pliki w paczce (2)
  • SKILL.json 1 KB
  • SKILL.md 24 KB

Wersje

RepozytoriumWynikLicencja
Ta strona · 420company/artemis85MIT
arcasilesgroup/ai-engineering100Apache-2.0

Migawka bazy z 28.10.2026 · wersja paczki a9da62f50635 (skrót SHA-256 całej paczki)

Pobrania w ostatnich 30 dniach: 0 · ranking

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 90vercel-ai
    Podpowiada, jak budować aplikacje i agenty AI na platformie Vercel, z SDK, bramką AI i MCP.
  • 100agent-native-architecture
    Pomaga projektować aplikacje agent-native: architektura autonomicznych agentów, narzędzia MCP i aplikacje, w których funkcje są wynikami działań agentów.
  • 100best-practices-for-agentic-development
    Wspiera projektowanie, budowę, przegląd i testowanie agentów, przepływów agentowych, skilli, serwerów MCP, interfejsów narzędzi i systemów subagentów.
  • 100mcp-client
    Łączy aplikacje z serwerami MCP i z nich korzysta: integracja serwerów, agenci AI używający narzędzi MCP, testowanie serwerów oraz programowe wywoływanie narzędzi i czytanie zasobów.
  • 91copilot-sdk
    Tworzy agentowe aplikacje z GitHub Copilot SDK, w tym osadza agentów AI, definiuje narzędzia, obsługuje strumieniowanie i sesje oraz łączy się z serwerami MCP.
  • 95copilot-sdk
    Buduje aplikacje agentowe z GitHub Copilot SDK: osadzanie agentów AI, własne narzędzia, strumieniowanie odpowiedzi, sesje, serwery MCP i własni agenci.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.