Skip to Content
ガイドGuideワークフロー: AI Recruiter

はじめに

このガイドでは、Mastra がどのようにして LLM を使ったワークフロー構築を支援するかを学びます。

候補者の履歴書から情報を収集し、そのプロフィールに応じて技術的な質問または行動に関する質問のいずれかに分岐するワークフローの作成手順を順を追って説明します。その過程で、ワークフローのステップの構成方法、分岐処理の扱い方、LLM 呼び出しの統合方法についても紹介します。

以下はワークフローの簡潔なバージョンです。必要なモジュールのインポートから始まり、Mastra のセットアップ、候補者データの抽出と分類のステップ定義、そして適切なフォローアップ質問の実施までを示しています。各コードブロックの後には、その内容と有用性についての簡単な説明が続きます。

1. インポートとセットアップ

ワークフローの定義とデータ検証を扱うために、Mastra ツールと Zod をインポートする必要があります。

src/mastra/index.ts
import { Mastra } from "@mastra/core"; import { Step, Workflow } from "@mastra/core/workflows"; import { z } from "zod";

.env ファイルに OPENAI_API_KEY を追加してください。

.env
OPENAI_API_KEY=<your-openai-key>

2. ステップ1:候補者情報の収集

履歴書のテキストから候補者の詳細を抽出し、それらを技術系か非技術系かに分類したいと考えています。このステップでは、LLMを呼び出して履歴書を解析し、名前、技術的ステータス、専門分野、元の履歴書テキストを含む構造化されたJSONを返します。コードはtriggerデータからresumeTextを読み取り、LLMにプロンプトを送り、後続のステップで使用するために整理されたフィールドを返します。

src/mastra/index.ts
import { Agent } from "@mastra/core/agent"; import { openai } from "@ai-sdk/openai"; const recruiter = new Agent({ name: "Recruiter Agent", instructions: `You are a recruiter.`, model: openai("gpt-4o-mini"), }); const gatherCandidateInfo = new Step({ id: "gatherCandidateInfo", inputSchema: z.object({ resumeText: z.string(), }), outputSchema: z.object({ candidateName: z.string(), isTechnical: z.boolean(), specialty: z.string(), resumeText: z.string(), }), execute: async ({ context }) => { const resumeText = context?.getStepResult<{ resumeText: string; }>("trigger")?.resumeText; const prompt = ` Extract details from the resume text: "${resumeText}" `; const res = await recruiter.generate(prompt, { output: z.object({ candidateName: z.string(), isTechnical: z.boolean(), specialty: z.string(), resumeText: z.string(), }), }); return res.object; }, });

3. 技術的な質問ステップ

このステップでは、技術職と判断された候補者に対して、どのようにしてその専門分野に入ったのかについて詳しく尋ねます。履歴書全体のテキストを使用することで、LLMが関連性の高いフォローアップ質問を作成できるようにしています。このコードは、候補者の専門分野に関する質問を生成します。

src/mastra/index.ts
interface CandidateInfo { candidateName: string; isTechnical: boolean; specialty: string; resumeText: string; } const askAboutSpecialty = new Step({ id: "askAboutSpecialty", outputSchema: z.object({ question: z.string(), }), execute: async ({ context }) => { const candidateInfo = context?.getStepResult<CandidateInfo>( "gatherCandidateInfo", ); const prompt = ` You are a recruiter. Given the resume below, craft a short question for ${candidateInfo?.candidateName} about how they got into "${candidateInfo?.specialty}". Resume: ${candidateInfo?.resumeText} `; const res = await recruiter.generate(prompt); return { question: res?.text?.trim() || "" }; }, });

4. 行動質問ステップ

候補者が非技術系の場合は、異なるフォローアップ質問が必要です。このステップでは、再度履歴書全体のテキストを参照しながら、その役割について最も興味がある点を尋ねます。コードは、LLMに役割に焦点を当てた質問を求めます。

src/mastra/index.ts
const askAboutRole = new Step({ id: "askAboutRole", outputSchema: z.object({ question: z.string(), }), execute: async ({ context }) => { const candidateInfo = context?.getStepResult<CandidateInfo>( "gatherCandidateInfo", ); const prompt = ` You are a recruiter. Given the resume below, craft a short question for ${candidateInfo?.candidateName} asking what interests them most about this role. Resume: ${candidateInfo?.resumeText} `; const res = await recruiter.generate(prompt); return { question: res?.text?.trim() || "" }; }, });

5. ワークフローの定義

ここでは、候補者の技術的なステータスに基づいて分岐ロジックを実装するために、これまでのステップを組み合わせます。ワークフローはまず候補者のデータを収集し、その後、isTechnical に応じて専門分野について質問するか、役割について質問します。コードでは、gatherCandidateInfo を askAboutSpecialty および askAboutRole と連結し、ワークフローを確定します。

src/mastra/index.ts
const candidateWorkflow = new Workflow({ name: "candidate-workflow", triggerSchema: z.object({ resumeText: z.string(), }), }); candidateWorkflow .step(gatherCandidateInfo) .then(askAboutSpecialty, { when: { "gatherCandidateInfo.isTechnical": true }, }) .after(gatherCandidateInfo) .step(askAboutRole, { when: { "gatherCandidateInfo.isTechnical": false }, }); candidateWorkflow.commit();

6. ワークフローを実行する

src/mastra/index.ts
const mastra = new Mastra({ workflows: { candidateWorkflow, }, }); (async () => { const { runId, start } = mastra.getWorkflow("candidateWorkflow").createRun(); console.log("Run", runId); const runResult = await start({ triggerData: { resumeText: "Simulated resume content..." }, }); console.log("Final output:", runResult.results); })();

これで、履歴書を解析し、候補者の技術力に基づいてどの質問をするかを決定するワークフローが完成しました。おめでとうございます、そしてハッキングを楽しんでください!