メインコンテンツへスキップ

Kimi K2.6 APIチュートリアル:AI求人検索アシスタントを構築する

Kimi K2.6、Olostep、OpenAI Agents SDKで、CVを読み込み、ライブの求人を見つけ、ノイズを除去し、応募先を的確に提示するAIエージェントを構築します。
更新 2026年5月7日  · 11 分 読む

Kimi K2.6はMoonshot AIの最新のオープンソースモデルで、コーディング、長期実行、ツール利用、エージェントワークフロー向けに設計されています。Kimi.com、Kimiアプリ、Kimi Code、そしてAPIを通じて利用でき、推論、ツール呼び出し、構造化出力を必要とする実用的なAIアプリケーションの構築に役立ちます。

このチュートリアルでは、JobFit AIというAI求人検索アシスタントを構築します。このアシスタントは候補者のCVを読み込み、最新の求人を検索し、選択した求人ページを確認して、適合度に基づくランキングレポートを生成します。Kimi K2.6は、長いコンテキストのワークフロー、ツール呼び出し、そしてKimi APIプラットフォームでの思考モードと非思考モードの両方をサポートしているため、このプロジェクトに最適です。

このプロジェクトで使用するもの:

  • Kimi K2.6(推論モデル)
  • Olostep(ライブのウェブ検索と求人ページのスクレイピング)
  • pypdf(候補者のCVからのテキスト抽出)
  • OpenAI Agents SDK(ツールを使うエージェントの構築)
  • Gradio(ワークフローをシンプルなウェブアプリに変換)

このチュートリアルの終わりまでに、ユーザーがCVをアップロードし、希望条件を記述して、1分以内に関連求人のランキングレポートを生成できるアプリが完成します。

エージェント型AIを始めたばかりの方は、当社の AI Agents Fundamentals スキルトラックへの登録を強くおすすめします。設計パターン、MCP、マルチエージェントシステムの基本をカバーしています。

チュートリアルの前提条件

開始前に以下を用意してください:

  • Python 3.11以上
  • KimiのAPIキー
  • Moonshot AIアカウントに$5以上のクレジット
  • OlostepのAPIキー
  • PDF形式のCV
  • Pythonの基礎知識

1. Python環境をセットアップする

新しいプロジェクトフォルダを作成します:

mkdir JobFit-AI
cd JobFit-AI

次に必要なパッケージをインストールします:

pip install gradio openai pypdf openai-agents

主なパッケージは次のとおりです:

  • gradio:ウェブインターフェースを作成

  • openai:OpenAI互換のAPIに接続

  • pypdf:PDFファイルからテキストを抽出

  • openai-agents:ツールを使うAIエージェントを作成

次にアカウントを作成し、APIキーを発行します:

  • 無料の Olostep アカウントを作成し、ダッシュボードからAPIキーを発行します。$9/月のStarterプランに登録すると、5,000リクエストが含まれます。アプリのテストとデプロイに十分なリクエスト数です。
  • Kimiプラットフォーム$5以上のクレジットを追加し、APIキーを発行します。

KimiとOlostepのAPIキーを環境変数として設定してください。MOONSHOT_API_KEYはKimi K2.6 APIへのアクセスに使用し、OLOSTEP_API_KEYはライブの求人ページの検索とスクレイピングに使用します。

2. プロジェクト設定を定義する 

Jupyter Notebookを起動し、新しいセルを作成して必要なインポートとプロジェクト設定を追加します。

import json
import os

import requests
from agents import Agent, AsyncOpenAI, ModelSettings, OpenAIChatCompletionsModel, RunConfig, Runner, function_tool, set_tracing_disabled
from IPython.display import Markdown, display
from pypdf import PdfReader

次に、モデル名、APIエンドポイント、エージェントの最大ターン数、CVのパス、求人の希望条件を定義します。

KIMI_MODEL = "kimi-k2.6"
KIMI_BASE_URL = "https://api.moonshot.ai/v1"
OLOSTEP_SEARCH_URL = "https://api.olostep.com/v1/searches"
OLOSTEP_SCRAPE_URL = "https://api.olostep.com/v1/scrapes"
MAX_AGENT_TURNS = 25


cv_path = "abid-resume.pdf"
preferences = """
Remote data science, AI writer, or technical writer roles in AI, machine learning, data science, or cloud.
Prefer technical content, tutorials, developer education, research writing, and AI product storytelling.
""".strip()


set_tracing_disabled(True)

KIMI_MODELKIMI_BASE_URLは、Moonshot AIのOpenAI互換APIエンドポイント経由でKimi K2.6を利用する設定です。OlostepのURLはライブの求人検索とページスクレイピングに使用します。

cv_pathは候補者の履歴書PDFへのパスです。PDFが同じプロジェクトフォルダに保存されていることを確認するか、別の場所にある場合はパスを更新してください。

preferencesは、どのような求人を探すかをエージェントに伝えるための変数です。対象ロール、業界、勤務地、シニアリティ、働き方の好みに合わせて更新できます。

また、set_tracing_disabled(True)でトレーシングを無効化します。これはOpenAI Agents SDKのデフォルト機能ですが、本プロジェクトはOpenAI互換エンドポイント経由でKimiを使用するため、トレーシングを無効にしてローカル設定を簡素化し、サードパーティモデルプロバイダーでのトレーシング関連の問題を回避します。

3. Kimi K2.6 APIに接続する

続いて、先ほど環境変数に保存したAPIキーを使ってKimiクライアントを設定します。

kimi_client = AsyncOpenAI(
   api_key=os.environ["MOONSHOT_API_KEY"],
   base_url=KIMI_BASE_URL,
)

これでKimi用のAPIクライアントが作成されます。api_keyMOONSHOT_API_KEYから読み込み、base_urlはMoonshot AIのOpenAI互換エンドポイントを指します。

次に、OpenAI Agents SDK内で使えるようにKimiモデルをラップします:

kimi_model = OpenAIChatCompletionsModel(
   model=KIMI_MODEL,
   openai_client=kimi_client,
)

続いてモデル設定を定義します:

model_settings = ModelSettings(
   tool_choice="auto",
   parallel_tool_calls=True,
   extra_body={"thinking": {"type": "disabled"}},
)

tool_choice="auto"は、ツールをいつ呼び出すかをエージェントに自動決定させます。parallel_tool_calls=Trueは必要に応じて複数のツール呼び出しを同時に実行できるようにします。

また、extra_body={"thinking": {"type": "disabled"}}でKimiの思考モードを無効化します。これにより、出力がよりクリーンになり、構造化されたJobFitレポートに適した形になります。

最後に実行設定を作成します:

run_config = RunConfig(
   workflow_name="JobFit AI Kimi Search",
   tracing_disabled=True,
)

workflow_nameはこの実行にわかりやすいラベルを付けます。ここでもトレーシングは無効のままにします。本プロジェクトはOpenAIのトレーシング基盤ではなく、OpenAI互換エンドポイント経由でKimiを使用するためです。

4. 候補者のCVからテキストを抽出する

次に、PdfReaderを使ってCVを読み込み、各ページからテキストを抽出します。

reader = PdfReader(cv_path)
cv_text = "\n".join(page.extract_text() or "" for page in reader.pages)[:12000]
print(f"Loaded {len(cv_text):,} characters from {cv_path}")

このコードはcv_pathで指定したPDFを読み込み、全ページのテキストを抽出して1つの文字列に結合します。

[:12000]の上限により、CVテキストはエージェントプロンプトに収まりやすい長さに抑えつつ、候補者の経験・スキル・希望に関する十分な文脈をモデルに与えます。

出力はCVファイル名や長さに応じて次のようになります:

Loaded 2,946 characters from abid-resume.pdf

これはCVが正常に読み込まれ、PDFから抽出された文字数が表示されていることを示します。

5. エージェントの指示を作成する 

次に、エージェントがどのように検索・ツール使用・最終レポートの整形を行うかを制御する指示を定義します。

AGENT_INSTRUCTIONS = """
You are JobFit AI, a focused job-search agent.

Tool plan:
- Call search_jobs exactly once with limit 8.
- Read at most 3 direct job pages with read_job_page.
- After reading up to 3 pages, stop using tools and write the report.
- Search again only if the first search returns zero usable jobs.
- Avoid broad search pages, expired jobs, and LinkedIn unless no better source exists.

Report rules:
- Keep the report simple, clear, and practical.
- Use short bullets.
- Do not use em dashes.
- Do not use contractions.
- Do not add text before or after the report.
- End after the final Job Notes entry.
- Include at least 5 ranked jobs if the search results contain at least 5 usable jobs.
- If only 3 pages were scraped, use backup jobs from search results when they look usable.
- Every job must include a clickable Markdown link.
- Every job must have one apply decision: Apply, Maybe, or Do not apply.

Use exactly this Markdown structure:

# JobFit AI Report

## Best Match

- **Role:** <job title>
- **Company:** <company>
- **Apply decision:** Apply / Maybe / Do not apply
- **Fit score:** <score>/100
- **Link:** [Apply here](<job url>)

**Why this is the best match:**

- <specific reason>
- <specific reason>
- <specific reason>

## Ranked Jobs

| Rank | Role | Company | Apply? | Fit | Link |
| --- | --- | --- | --- | --- | --- |
| 1 | <role> | <company> | Apply / Maybe / Do not apply | <score>/100 | [Apply here](<url>) |

## Job Notes

### 1. <Role> at <Company>

- **Apply decision:** Apply / Maybe / Do not apply
- **Fit score:** <score>/100
- **Link:** [Apply here](<job url>)

**Why it fits:**

- <bullet>
- <bullet>

**Concerns:**

- <bullet>
- <bullet>

**Application angle:**

- <how the person should position their CV/application>
""".strip()

これらの指示により、エージェントの焦点が定まり、求人検索は1回、求人ページの閲覧は最大3ページ、レポート構造は固定のMarkdownに制限されます。

また、短い箇条書き、クリック可能なリンク、適合度スコア、各職種ごとの明確な応募判断を必須とすることで、出力は読みやすくなります。

6. 実行時プロンプトを作成する

エージェントの指示を定義したら、各実行時にエージェントへ渡すプロンプトテンプレートを作成します。

RUN_PROMPT_TEMPLATE = """
Find current job postings for this candidate and rank them by fit.

Keep the run simple:
- one search
- up to three page reads
- final report

The final report must follow AGENT_INSTRUCTIONS exactly.
Use simple wording. Do not use em dashes. Do not use contractions.

Candidate CV:
{cv_text}

Preferences:
{preferences}
""".strip()

このプロンプトは、実行時に候補者のCVのテキストと求人の希望条件を組み合わせます。

cv_textプレースホルダには抽出したCV内容が、preferencesには先ほど定義した希望条件が入ります。これらにより、エージェントは関連する求人を検索し、適合度で順位付けするための十分な文脈を得ます。

7. Olostepでライブ検索を追加する

エージェントの指示と実行時プロンプトの準備ができたら、Olostepを使ってウェブ検索と求人ページの閲覧を可能にする2つのツールを追加します。

最初のツールは求人一覧をウェブ検索し、コンパクトな結果リストを返します。

@function_tool
def search_jobs(query: str, limit: int = 8) -> str:
    """Search the web for job listings and return compact JSON results."""
    response = requests.post(
        OLOSTEP_SEARCH_URL,
        headers={"Authorization": f"Bearer {os.environ['OLOSTEP_API_KEY']}", "Content-Type": "application/json"},
        json={"query": query},
        timeout=60,
    )
    response.raise_for_status()
    links = response.json().get("result", {}).get("links", [])[:limit]
    results = [
        {"title": item.get("title", "Untitled"), "url": item.get("url"), "description": item.get("description", "")}
        for item in links
        if isinstance(item, dict) and item.get("url")
    ]
    return json.dumps(results, ensure_ascii=False)

@function_toolデコレータにより、このPython関数は呼び出し可能なツールとしてエージェントに提供されます。

エージェントが求人一覧を必要とすると、search_jobsを検索クエリ付きで呼び出します。関数はOlostepの検索エンドポイントにクエリを送信し、上位結果を収集してJSONで返します。

各結果には以下が含まれます:

  • 職種名
  • 求人URL
  • 短い説明

2つ目のツールは特定の求人ページを開いて読み取ります。

@function_tool
def read_job_page(url: str) -> str:
    """Scrape one job listing URL and return markdown text."""
    response = requests.post(
        OLOSTEP_SCRAPE_URL,
        headers={"Authorization": f"Bearer {os.environ['OLOSTEP_API_KEY']}", "Content-Type": "application/json"},
        json={"url_to_scrape": url, "formats": ["markdown"]},
        timeout=120,
    )
    response.raise_for_status()
    markdown = response.json().get("result", {}).get("markdown_content") or ""
    return markdown[:8000]

この関数は求人URLをOlostepのスクレイプエンドポイントに送り、ページ内容をMarkdown形式で返します。

[:8000]の上限により、スクレイピングしたページはエージェントが処理しやすい長さに保たれつつ、職務内容、要件、企業情報などの有用な詳細を十分に保持します。

8. JobFit AIエージェントを作成する

ここまでで定義したKimiモデル、モデル設定、Olostepのツール、エージェント指示を接続してエージェントを作成します。

agent = Agent(
   name="JobFit AI",
   model=kimi_model,
   model_settings=model_settings,
   tools=[search_jobs, read_job_page],
   instructions=AGENT_INSTRUCTIONS,
)

Agentオブジェクトがこのワークフローのメインコントローラです。

このエージェントは次を使用します:

  • kimi_model(推論モデル)
  • model_settings(ツール使用と出力動作の制御)
  • search_jobs(ライブの求人検索)
  • read_job_page(選択した求人ページのスクレイピング)
  • AGENT_INSTRUCTIONS(厳密な検索とレポートルールの遵守)

これでエージェントは求人を検索し、候補者のCVと照合し、構造化されたJobFit AIレポートを生成できる状態になりました。

9. エージェントのワークフローを実行する

抽出したCVテキストと先ほど定義した求人希望を使って、JobFit AIエージェントを実行します。

まず実行時プロンプトを整形します:

prompt = RUN_PROMPT_TEMPLATE.format(cv_text=cv_text, preferences=preferences)

これにより、テンプレートに候補者のCVと希望条件が差し込まれます。

次にストリーミング実行を開始します:

print("Starting agent run")


result = Runner.run_streamed(
   agent,
   prompt,
   max_turns=MAX_AGENT_TURNS,
   run_config=run_config,
)

Runner.run_streamed()はエージェントのワークフローを開始し、発生するイベントを逐次ストリーミングします。ツールの呼び出し、ツール出力の受信、最終メッセージの作成タイミングが把握しやすくなります。

続いてストリーミングループを追加します:

async for event in result.stream_events():
   if event.type == "agent_updated_stream_event":
       print(f"Agent: {event.new_agent.name}")
   elif event.type == "run_item_stream_event":
       item = event.item
       if event.name == "tool_called":
           raw = item.raw_item
           tool_name = raw.get("name") if isinstance(raw, dict) else getattr(raw, "name", "tool")
           arguments = raw.get("arguments") if isinstance(raw, dict) else getattr(raw, "arguments", "")
           arguments = str(arguments).replace(chr(10), " ")[:500]
           print(f"Tool call: {tool_name}")
           if arguments:
               print(f"Parameters: {arguments}")
       elif event.name == "tool_output":
           print(f"Tool output: {len(str(item.output)):,} chars")
       elif event.name == "message_output_created":
           print("Final message ready")

このループは実行中の進捗をわかりやすく表示します。たとえば、エージェントが求人を検索したり、求人ページを読んだり、レポートの生成を完了したことがわかります。

最後に、最終出力をreportという変数に保存します:

report = result.final_output
globals()["report"] = report


print("Run complete")
print(f"Model responses: {len(result.raw_responses)}")
print(f"Run items: {len(result.new_items)}")
print(f"Final output: {len(str(report)):,} chars")

report変数には最終的なJobFit AIレポートが格納されます。これを表示したり保存したり、Gradioアプリ内で使用できます。

出力は次のようになります:

Starting agent run
Agent: JobFit AI
Tool call: search_jobs
Parameters: {"query":"remote data science writer technical writer AI machine learning content editor","limit":8}
Tool output: 2,445 chars
Tool call: read_job_page
Parameters: {"url":"https://www.indeed.com/q-data-science-writer-jobs.html"}
Tool output: 8,000 chars
Tool call: read_job_page
Parameters: {"url":"https://www.builtinnyc.com/jobs/remote/data-analytics/data-science"}
Tool output: 8,000 chars
Tool call: read_job_page
Parameters: {"url":"https://www.virtualvocations.com/jobs/q-data+scientist+remote+jobs/c-writing/d-336"}
Tool output: 5,075 chars
Final message ready
Run complete
Model responses: 5
Run items: 13
Final output: 5,931 chars

この出力は、エージェントが求人を検索し、選択したページを読み取り、最終レポートを正常に生成したことを示します。

10. 生成されたJobFitレポートを表示する

エージェントの実行が完了したら、最終レポートをMarkdown形式で表示します。

display(Markdown(report))

これにより、生成されたJobFit AIレポートがノートブック内にMarkdownとしてレンダリングされ、プレーンテキストより読みやすくなります。

レポートには、最適な求人、ランキング一覧、適合度スコア、応募判断、懸念点、応募戦略が含まれます。

Generated JobFit Report with Kimi k2.6

11. ワークフローをGradioのウェブアプリにする

ノートブックでワークフローをテストしたら、シンプルなGradioのウェブアプリに変換できます。app.pyファイルを作成し、GitHubプロジェクトの JobFit-AI/app.py のコードをコピーしてローカルのファイルに貼り付けます。

次のコマンドでアプリを起動します:

python app.py

Gradio app running locally

その後、表示されたローカルURL(この例ではhttp://127.0.0.1:7860/)をブラウザで開きます:

Jobfit AI Gradio web UI

Gradioアプリは、求人適合レポートを生成するためのシンプルなインターフェースを提供します。次の要素が含まれます:

  • CVのPDFをアップロードするフィールド(履歴書をアップロード)
  • 希望する職種を記述するテキストボックス(職種タイプ、業界、勤務地、シニアリティ、関心トピックなど)
  • エージェントのワークフローを開始する「Generate JobFit Report」ボタン
  • 実行中に表示される非表示の進捗ログ(CVの読み取り、ツール呼び出し、ツール出力の受信などの処理内容を表示)
  • エージェントの完了後にランキング付きの求人適合レポートを表示する最終Markdown領域

アプリの裏側では、アップロードされたCVを読み込み、テキストを抽出し、CVと希望条件をJobFit AIエージェントに送信して、Olostepでライブの求人一覧を検索します。最大3つの求人ページを読み取り、ランキング、適合度スコア、応募判断、懸念点、応募戦略を含む構造化されたMarkdownレポートを返します。

12. CVをアップロードしてレポートを生成する

CVまたは履歴書のPDFをアップロードし、「Generate JobFit Report」をクリックしてウェブアプリをテストします。

この例では、実務経験約3年のCVをアップロードし、アプリが候補者のプロフィールと希望に基づいて関連する求人を見つけられるかを確認しました。レポートは1分未満で生成されました。

アプリの実行中、進捗ログには次のような各ステップが表示されます:

  • CVの読み取り
  • 各ページからのテキスト抽出
  • エージェント実行の開始
  • 求人検索ツールの呼び出し
  • ツール出力の返却

JobFit AI Progress Logs

実行が完了すると、アプリは最終レポートをMarkdown形式で表示します。

レポートは最適な求人から始まり、続いてランキング表が表示されます。各職種について、適合度スコア、応募判断、適合理由、懸念点、応募戦略が詳しく示されます。

Generated JobFit AI Report

この例では、最上位はNannyMLのSenior Data Science Writerの募集でした。候補者のデータサイエンス、テクニカルライティング、AIコンテンツのバックグラウンドと一致しており、強い適合に見えました。

レポート内の「Apply here」リンクをクリックすると、求人ページを開いて応募前に詳細を確認できます。

NannyML Job Posting

注意:ローカルでの実行に問題が発生した場合は、GitHubリポジトリ kingabzpro/JobFit-AI を確認してください。ノートブック、app.py、セットアップ手順が含まれており、依存関係のインストールやローカル実行を支援します。

まとめ

JobFit AIは、Kimi K2.6、Olostep、OpenAI Agent SDKを活用して、職種を変える人や積極的に応募している人が抱えがちな2つの課題を解決します。

1つ目はどこに応募すべきかがわからないことです。求人サイト、プラットフォーム、企業の採用ページは多数ありますが、どれが時間を割く価値のある募集なのかは明確ではありません。このアプリは候補者のCVと希望条件を用いて、より適した求人に絞り込みます。

2つ目は求人件数が多すぎて絞り込みが難しいことです。すべての求人サイトを手作業で確認する代わりに、エージェントがライブの求人を検索し、選択したページを読み取り、最適な求人、ランキング、適合度、懸念点、応募戦略を含む構造化レポートを作成します。これにより、実際に応募する価値のある職種に集中しやすくなります。

また、Kimi K2.6 APIはこのエージェント型ワークフローでも良好に機能しました。高速で信頼性が高く、構造化された指示に従う能力も優れていました。テストでは、エージェントに最大25ターンを許可すると、より多くのページを深く検索・スクレイプできましたが、実行時間は約5分でした。品質と速度のバランスを取るため、検索1回・ページ閲覧最大3回に制限し、1分未満でレポートを生成できるようにしました。

許可するステップ数、検索結果数、ページ閲覧数を増やすことで、求人レポートの品質を高められます。たとえば、エージェントの上限を30ターンに増やし、より多くの求人ページを読ませると、より多くの職種と強力な推薦を含む深いレポートを作成できます。ただし、その分、実行時間とAPI使用量も増加します。

同様のエージェント型ツールの構築に興味があれば、以下のAPIチュートリアルもご覧ください:

Kimi K2.6 よくある質問(FAQ)

Kimi K2.6とは何ですか?

Kimi K2.6はMoonshot AIが2026年4月にリリースした最新のオープンウェイトのエージェント向けモデルです。Mixture-of-Experts(MoE)アーキテクチャに基づき、総パラメータは約1兆、推論時に有効化されるのは一度のフォワードパスで320億で、コーディング、ツール利用、長期的なエージェントタスクに最適化されています。

Kimi K2.6のコンテキストウィンドウは?

Kimi K2.6は262,144トークン(256K)のコンテキストウィンドウをサポートします。これにより、コードベース全体、長文ドキュメント、またはマルチステップのエージェント実行を1つのセッションで処理するのに適しています。

Kimi K2.6のAPI料金はいくらですか?

Kimi APIを直接利用する場合、入力トークンは$0.95/100万(キャッシュミス)と$0.16/100万(キャッシュヒット)、出力は$4.00/100万トークンです。サードパーティプロバイダーでは一部でより低価格が提供されており、入力$0.60/100万、出力$2.80/100万からの料金があります。

Kimi K2.6は思考モードをサポートしますか?

はい。Kimi K2.6は思考モード(拡張推論)とインスタントモード(より高速な非思考応答)の両方をサポートします。本チュートリアルでは、extra_body={"thinking": {"type": "disabled"}}で思考モードを明示的に無効化し、出力をよりクリーンかつ高速にしています。

エージェント向けコーディング系ベンチマークでのKimi K2.6の性能は?

Kimi K2.6はSWE-Bench Verifiedで80.2を記録し、そのレベルでは最強のオープンソースモデルで、Claude Opus 4.6(80.8%)やGemini 3.1 Pro(80.6%)といったクローズドモデルにわずかに及ばない性能です。BrowseCompでは83.2、Agent Swarmモードでは86.3となり、GPT-5.5 Pro(90.1)や未公開のClaude Mythos Preview(86.9)に次ぐ位置付けです。

トピック

DataCampでエージェント型AIを学ぼう!

Courses

OpenAI APIを使いこなす

3時間
139.6K
OpenAI APIを使った、AIアプリ開発の第一歩を踏み出しましょう。 ChatGPTのような人気AIアプリの幅広い機能を学びます。
詳細を見るRight Arrow
コースを開始
もっと見るRight Arrow