mcpField
C
Convex Agents Files

Convex Agents Files

github.com/sstoboエージェントワークフロー24197 回インストール40 週間前に更新
リポジトリ

Convex Agents Files について

Convex Agents Filesは、Convexでエージェントを構築する開発者向けのスキルです。ファイルの保存、メッセージへの添付、画像処理、クリーンアップに加え、画像生成やファイル参照の追跡を扱います。

主な機能

  1. 01アップロードファイルの保存
  2. 02メッセージへのファイル添付
  3. 03ファイルのインライン処理
  4. 04画像の生成と保存
  5. 05メタデータ追跡とクリーンアップ

活用シーン

  1. 01ユーザーがアップロードした画像の分析
  2. 02エージェントのワークフローでの文書処理
  3. 03会話メッセージへのファイル添付
  4. 04参照されなくなったファイルの削除

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/sstobo/convex-skills --skill convex-agents-files

インストール後、Claude Code で/convex-agents-filesを入力して読み込まれたか確認します。

詳細

目的

ファイルや画像を使うと、エージェントは視覚コンテンツを理解し、生成できます。アップロード、保存、メッセージへの添付、ファイルのライフサイクル管理について説明します。

このスキルを使用する場面

  • ユーザーがエージェントによる分析用に画像をアップロードする
  • エージェントがドキュメントやファイルを処理する必要がある
  • エージェントが DALL-E で画像を生成する
  • ファイルベースのワークフローを構築する
  • ファイルのクリーンアップと追跡を実装する

ファイルをアップロードして保存する

import { storeFile } from "@convex-dev/agent";

export const uploadFile = action({
  args: { fileData: v.string(), filename: v.string(), mimeType: v.string() },
  handler: async (ctx, { fileData, filename, mimeType }) => {
    const bytes = Buffer.from(fileData, "base64");

    const { file } = await storeFile(
      ctx,
      components.agent,
      new Blob([bytes], { type: mimeType }),
      { filename, sha256: "hash" }
    );

    return {
      fileId: file.fileId,
      url: file.url,
      storageId: file.storageId,
    };
  },
});

メッセージと一緒にファイルを送信する(2 ステップ)

先にアップロードしてから、添付ファイル付きのメッセージを送信します。

import { saveMessage, getFile } from "@convex-dev/agent";

// Step 1: Save message with file
export const submitFileQuestion = mutation({
  args: { threadId: v.string(), fileId: v.string(), question: v.string() },
  handler: async (ctx, { threadId, fileId, question }) => {
    const { imagePart, filePart } = await getFile(ctx, components.agent, fileId);

    const { messageId } = await saveMessage(ctx, components.agent, {
      threadId,
      message: {
        role: "user",
        content: [
          imagePart ?? filePart,
          { type: "text", text: question },
        ],
      },
      metadata: { fileIds: [fileId] },
    });

    return { messageId };
  },
});

// Step 2: Generate response
export const generateFileResponse = action({
  args: { threadId: v.string(), promptMessageId: v.string() },
  handler: async (ctx, { threadId, promptMessageId }) => {
    const { thread } = await myAgent.continueThread(ctx, { threadId });
    await thread.generateText({ promptMessageId });
  },
});

ファイルをインラインで保存する(アクションのみ)

生成時にファイルを直接渡します。

export const analyzeImageInline = action({
  args: { threadId: v.string(), imageData: v.string(), question: v.string() },
  handler: async (ctx, { threadId, imageData, question }) => {
    const { thread } = await myAgent.continueThread(ctx, { threadId });

    await thread.generateText({
      message: {
        role: "user",
        content: [
          {
            type: "image",
            image: Buffer.from(imageData, "base64"),
            mimeType: "image/png",
          },
          { type: "text", text: question },
        ],
      },
    });
  },
});

画像を生成して保存する

export const generateAndSaveImage = action({
  args: { threadId: v.string(), prompt: v.string() },
  handler: async (ctx, { threadId, prompt }) => {
    const { image } = await generateImage({
      model: openai.image("dall-e-2"),
      prompt,
    });

    const { file } = await storeFile(ctx, components.agent, image, {
      filename: `generated-${Date.now()}.png`,
    });

    return { fileId: file.fileId };
  },
});

主な原則

  • 自動保存:64 KB を超えるファイルは自動的に保存されます
  • ファイルの追跡:メタデータによって、どのメッセージがファイルを参照しているかを追跡します
  • URL の生成:署名付き URL により、不正なアクセスを防ぎます
  • MIME タイプの推定:指定されていない場合、自動的に検出されます
  • クリーンアップ:ガベージコレクション用にファイルが追跡されます

次のステップ

  • メッセージ管理については messages を参照してください
  • ストリーミングによるファイル処理については streaming を参照してください
  • エージェントのセットアップについては fundamentals を参照してください

コメント