Skip to content

How-to:CrewAIテンプレートの修正

このチュートリアルでは、ローカルで作成された簡単なエージェントワークフローを使って、DataRobot Agent Templatesリポジトリを利用し、このエージェントをDataRobotフレームワークに迅速に実装する方法を説明します。 DataRobotによってデプロイされたグローバルツールを実装した、より複雑なエージェントワークフローについては、CrewAIエージェントを備えたデータレジストリのグローバルツールを参照してください。

datarobot-agent-templatesリポジトリのクローンを作成する

エージェントワークフローの構築を開始するには、パブリックリポジトリであるdatarobot-agent-templatesのクローンを作成します。 このリポジトリには、マルチエージェントフレームワークでのAIエージェントの構築およびデプロイのための、すぐに使えるテンプレートが用意されています。 これらのテンプレートを使用すると、最小限の設定要件で独自のエージェントを簡単に設定できます。

まず、開発環境のコマンドライン/ターミナルと以下のコマンドを使用して、DataRobot Agent Templatesリポジトリのクローンを作成します。

git clone --branch 11.3.5 --depth 1 https://github.com/datarobot-community/datarobot-agent-templates.git
cd datarobot-agent-templates 

datarobot-agent-templates version

この基本ステップでは、バージョン11.3.5のdatarobot-agent-templatesリポジトリを使用します。 Ensure that the workspace used for this walkthrough is on that version. Newer versions may not be compatible with the code provided below.

GitHubクローンのURL

GitHubリポジトリのクローン作成の詳細については、GitHubのドキュメントを参照してください。

カスタムエージェントコードをDataRobotのエージェントテンプレートに取り込む

ローカルエージェントワークフローをDataRobot Agentic AI Platformに統合する場合、DataRobot Agent Templatesリポジトリは、定型コード、テスト機能、デプロイパイプラインを提供することで、ローカル開発プロセスを迅速化します。 DataRobot Agentic AI Platformの外部で作成したエージェントにテンプレートが存在する場合は、既存のテンプレートを使用します。 DataRobotには、CrewAI、LangGraph、Llama-Index向けのエージェントワークフローテンプレートが用意されています。 使用しているフレームワークにテンプレートが存在しない場合は、Generic Baseテンプレートを使用します。

この例では、大規模言語モデル(LLM)に対し、「プロンプトに基づいてマーケティングコピーを生成するCrewAIエージェント」を作成するように要求しました。結果として得られる出力は、CrewAIテンプレートとの統合に適しています。 出力されたCrewAIエージェントは、.envファイルとPythonスクリプト(marketing_crew.py)で構成されています。

.env
# .env file
OPENAI_API_KEY="sk-your-openai-api-key-here"
SERPER_API_KEY="your-serper-api-key-here" 
marketing_crew.py
# marketing_crew.py

import os
from dotenv import load_dotenv
from crewai import Agent, Task, Crew, Process
from crewai_tools import SerperDevTool

# Load environment variables from .env file
load_dotenv()

# --- 1. Tool Setup ---
# Initialize the search tool. This allows agents to perform web searches.
# It uses the SERPER_API_KEY from your .env file.
search_tool = SerperDevTool()

# --- 2. Agent Definitions ---
# Each agent has a specific role, goal, and backstory. This helps the LLM
# to adopt a particular persona and focus on its specific task.

# Agent 1: Market Researcher
researcher = Agent(
role='Senior Market Researcher',
goal='To find and analyze the target audience and marketing angles for a given product',
backstory="""You are a seasoned market researcher with a knack for uncovering consumer insights.
You excel at identifying demographics, psychographics, and the key pain points of a target audience.
Your analysis forms the foundation of any successful marketing campaign.""",
verbose=True,  # Enables detailed logging of the agent's thought process
allow_delegation=False,
tools=[search_tool] # Assign the search tool to this agent
)

# Agent 2: Marketing Copywriter
copywriter = Agent(
role='Expert Marketing Copywriter',
goal='To write compelling and persuasive marketing copy based on market research',
backstory="""You are a world-class copywriter, known for your ability to weave words that sell.
You take research and transform it into captivating headlines, engaging social media posts,
and persuasive product descriptions. Your copy is clear, concise, and converts.""",
verbose=True,
allow_delegation=False
)

# Agent 3: Review and Editing Specialist
editor = Agent(
role='Chief Editor and Marketing Strategist',
goal='To review and refine marketing copy for clarity, tone, brand alignment, and effectiveness',
backstory="""You are a meticulous editor with a deep understanding of marketing strategy.
You have a keen eye for detail and ensure that all copy is not only grammatically perfect
but also aligns with the brand's voice and strategic goals. You provide the final polish.""",
verbose=True,
allow_delegation=False
)

# --- 3. Task Definitions ---
# Tasks are the specific assignments for the agents.
# The 'context' parameter is crucial as it passes the output of one task to the next.

# Task 1: Research the product
research_task = Task(
description="""Analyze the provided product: '{product_description}'.
Identify the primary target audience, their key pain points, and desires.
Research competitors and identify unique selling propositions (USPs).
The final output should be a concise report with actionable insights.""",
expected_output="""A report containing:
1. Target Audience Profile (demographics, interests, online behavior).
2. Key Pain Points and Desires of the audience.
3. A list of 3-5 Unique Selling Propositions (USPs) for the product.
4. Competitor analysis summary.""",
agent=researcher # Assign this task to the researcher agent
)

# Task 2: Write the marketing copy
copywriting_task = Task(
description="""Using the market research report, write three distinct pieces of marketing copy for the product: '{product_description}'.
The copy should be tailored to the identified target audience.
The pieces are:
1. A catchy Facebook ad post (approx. 50-80 words).
2. An engaging email subject line and a short preview text.
3. A persuasive product description for an e-commerce website (approx. 100-150 words).""",
expected_output="""A document with three sections:
1. Facebook Ad Copy.
2. Email Subject Line and Preview.
3. E-commerce Product Description.""",
agent=copywriter
)

# Task 3: Review and refine the copy
review_task = Task(
description="""Review the marketing copy provided. Check for grammatical errors, clarity, and brand voice alignment.
Ensure the copy is persuasive and directly addresses the target audience's pain points identified in the research.
Provide a final, polished version of all three copy pieces with constructive feedback.""",
expected_output="""The final, production-ready marketing copy for all three formats,
along with a brief note on any significant changes made and why.""",
agent=editor
)


# --- 4. Crew Assembly ---
# The Crew object brings the agents and tasks together.
# The process determines how the tasks are executed (e.g., sequentially).
marketing_crew = Crew(
agents=[researcher, copywriter, editor],
tasks=[research_task, copywriting_task, review_task],
process=Process.sequential,  # Tasks will be executed one after another
verbose=2 # Verbose logging level (0, 1, or 2)
)

# --- 5. Execution ---
# The kickoff method starts the crew's work.
# We provide the initial input as a dictionary.
product_prompt = {
    'product_description': 'A new, eco-friendly, smart coffee mug that keeps your drink at the perfect temperature for 3 hours. It is controlled by a mobile app and made from recycled materials.'
}

result = marketing_crew.kickoff(inputs=product_prompt)

print("\n\n########################")
print("## Here is the final result:")
print("########################\n")
print(result) 

環境の設定

上記のコードをテンプレートに統合する前に、CrewAIテンプレートを設定して実装をブートストラップします。 datarobot-agent-templatesリポジトリディレクトリで、ターミナルを開き、以下のコマンドを使用して、提供されたテンプレート環境ファイル(.env.template)をコピーし、名前を変更します。 このファイルで、必要な環境変数を定義します。

cp .env.template .env 

新しい.envファイルを探して開きます。 このファイルにDATAROBOT_API_TOKENおよびDATAROBOT_ENDPOINT環境変数を定義します。 次に、PULUMI_CONFIG_PASSPHRASEを定義する文字列を指定します。

DataRobot credentials in codespaces

DataRobotのCodespaceを使用している場合は、ファイルからDATAROBOT_API_TOKENおよびDATAROBOT_ENDPOINT環境変数を削除します。これらはCodespace環境にすでに存在しているためです。

これらの値は、.envファイルからキーと値のペアを読み込むために、(Taskfileに実装されている)dotenvを使ってagent.pyファイルにロードされます。

CrewAI実行のクイックスタート

次に、task startを使ってquickstart.pyを実行し、CrewAIのテンプレートを選択します。

task start 

CrewAIのテンプレートを選択するには、1を押し、Enterを押して選択を確定します。

Example start command
task start
task: [start] uv run quickstart.py
*****           *          ****        *             *  
*    *  ***   *****  ***   *   *  ***  ****   ***  *****
*    * *   *    *   *   *  ****  *   * *  *  *   *   *  
*****   *** *   *    *** * *   *  ***  ****   ***    *  

--------------------------------------------------------
           Quickstart for DataRobot AI Agents           
--------------------------------------------------------
Checking environment setup for required pre-requisites...
All pre-requisites are installed.


You will now select an agentic framework to use for this project.
For more information on the different agentic frameworks please go to:
  https://github.com/datarobot-community/datarobot-agent-templates/blob/main/docs/getting-started.md

Please select an agentic framework to use:
1. agent_crewai
2. agent_generic_base
3. agent_langgraph
4. agent_llamaindex
5. agent_nat
Enter your choice (1-5): 1 

次に、YEnterの順に押して、前提条件をインストールし、選択したエージェントの環境を設定します。

Example install prompt
Would you like to setup the uv python environments and install pre-requisites now?
(y/n): y 

Running these commands configures the environment for the agent_crewai template, removes all unnecessary files, and prepares the virtualenv to install the additional libraries required to run the selected agent template.

インストール済みの環境は、いつでも以下のコマンドを実行することで更新できます。

task install 

必要に応じて、エージェントテンプレートをカスタマイズする前に、変更なしでエージェントを実行して、コードをテストします。

task agent:cli START_DEV=1 -- execute --user_prompt 'Hi, how are you?' 

これで、agent_crewai/custom_modelディレクトリでエージェントのコードをカスタマイズできます。 この基本ステップでは、環境は変更しません。

すべてのタスクコマンドを表示する

task startを実行する前に、プロジェクトで使用可能なタスクを表示するには、以下のようにtaskコマンドを実行します。

 task
task: Available tasks for this project:
* default:       ℹ️ Show all available tasks (run `task --list-all` to see hidden tasks)
* install:       Install dependencies for all agent components and infra      (aliases: req, install-all)
* start:         ‼️ Quickstart for DataRobot Agent Templates ‼️ 

task startを実行してフレームワークを選択した後に、プロジェクトで使用可能なタスクを表示するには、以下のようにtaskコマンドを実行します。

 task
task: Available tasks for this project:
* default:                           ℹ️ Show all available tasks (run `task --list-all` to see hidden tasks)
* install:                           🛠️ Install all dependencies for agent and infra
* agent:install:                     🛠️ [agent_crewai] Install agent uv dependencies      (aliases: agent:req)
* agent:add-dependency:              🛠️ [agent_crewai] Add provided packages as a new dependency to an agent
* agent:cli:                         🖥️ [agent_crewai] Run the CLI with provided arguments
* agent:dev:                         🔨 [agent_crewai] Run the development server
* agent:dev-stop:                    🛑 [agent_crewai] Stop the development server
* agent:chainlit:                    🛝 Run the Chainlit playground
* agent:create-docker-context:       🐳 [agent_crewai] Create the template for a local docker_context image
* agent:build-docker-context:        🐳 [agent_crewai] Build the Docker image
* infra:install:                     🛠️ [infra] Install infra uv dependencies
* infra:build:                       🔵 Deploy only playground testing resources with pulumi
* infra:deploy:                      🟢 Deploy all resources with pulumi
* infra:refresh:                     ⚪️ Refresh and sync local pulumi state
* infra:destroy:                     🔴 Teardown all deployed resources with pulumi 
 task --list-all
task: Available tasks for this project:
* build:                             
* default:                           ℹ️ Show all available tasks (run `task --list-all` to see hidden tasks)
* deploy:                            
* destroy:                           
* install:                           🛠️ Install all dependencies for agent and infra
* agent:add-dependency:              🛠️ [agent_crewai] Add provided packages as a new dependency to an agent
* agent:build-docker-context:        🐳 [agent_crewai] Build the Docker image
* agent:chainlit:                    🛝 Run the Chainlit playground
* agent:cli:                         🖥️ [agent_crewai] Run the CLI with provided arguments
* agent:create-docker-context:       🐳 [agent_crewai] Create the template for a local docker_context image
* agent:dev:                         🔨 [agent_crewai] Run the development server
* agent:dev-stop:                    🛑 [agent_crewai] Stop the development server
* agent:install:                     🛠️ [agent_crewai] Install agent uv dependencies      (aliases: agent:req)
* agent:lint:                        
* agent:lint-check:                  
* agent:test:                        
* agent:test-coverage:               
* agent:update:                      
* infra:build:                       🔵 Deploy only playground testing resources with pulumi
* infra:deploy:                      🟢 Deploy all resources with pulumi
* infra:destroy:                     🔴 Teardown all deployed resources with pulumi
* infra:info:                        
* infra:init:                        
* infra:install:                     🛠️ [infra] Install infra uv dependencies
* infra:install-pulumi-plugin:       
* infra:lint:                        
* infra:lint-check:                  
* infra:pulumi:                      
* infra:refresh:                     ⚪️ Refresh and sync local pulumi state
* infra:select:                      
* infra:select-env-stack:            
* infra:test:                        
* infra:test-coverage: 

また、使用可能なすべてのエージェントCLIコマンドを表示するには、task agent:cliを実行します。

カスタムエージェントコードの統合

DataRobot Agentic AI Platformの外部でローカルに生成されたカスタムエージェントコードは、最小限の変更でagent_crewaiテンプレートに統合できます。 上のエージェント例を実装するには、.envファイルとagent.pyファイルの内容を変更します。 その他のファイルはすべて変更不要です。

.envファイルの内容を変更する

ローカルで開発されたエージェント用に生成された最初のファイルは、.envファイルでした。 必要であることが確認された資格情報は、OPENAI_API_KEYおよびSERPER_API_KEYです。 OPENAI_API_KEYは、エージェントのベースLLM用です。ただし、DataRobotのエージェントには必要ありません。 SERPER_API_KEYは、CrewAIの組み込みGoogle Serper Searchツールを使用するために必要です。 このツールには、APIにアクセスするための無料アカウントが必要です。

CrewAIの組み込みGoogle Serper Searchツールを使用するには、datarobot-agent-templatesディレクトリ(DATAROBOT_API_TOKENDATAROBOT_ENDPOINTが定義されているディレクトリ)のルートにある.envファイルにSERPER_API_KEYを追加します。 エージェントコードは、デプロイ時にランタイムパラメーターから、またはローカル開発時に環境ファイルから、このキーを自動的にロードします。

.env file
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Refer to https://docs.datarobot.com/en/api/dev-learning/api-quickstart.html#create-a-datarobot-api-key
# and https://docs.datarobot.com/en/docs/api/dev-learning/api-quickstart.html#retrieve-the-api-endpoint
# Can be deleted on a DataRobot codespace
DATAROBOT_API_TOKEN=<DATAROBOT_API_TOKEN>
DATAROBOT_ENDPOINT=https://app.datarobot.com/api/v2
SERPER_API_KEY=<SERPER_API_KEY>

# Required, unless logged in to Pulumi cloud. Choose your own alphanumeric passphrase to be used for encrypting Pulumi config
PULUMI_CONFIG_PASSPHRASE=<PULUMI_CONFIG_PASSPHRASE>

# If empty, a new use case will be created
DATAROBOT_DEFAULT_USE_CASE=

# To create a new LLM Deployment instead of using the LLM Gateway, set this to false.
# If you are using the LLM Gateway you must enable the `ENABLE_LLM_GATEWAY` feature flag in the DataRobot UI.
USE_DATAROBOT_LLM_GATEWAY=true

# Set this to an existing LLM deployment ID if you want to use a custom LLM deployment
# instead of creating new
LLM_DEPLOYMENT_ID=

# Specify the default execution environment for agents.
# The default agents environment is "[DataRobot] Python 3.11 GenAI Agents", you can alternatively replace
# this with the ID of an existing execution environment. If you leave this empty, a new execution environment
# will be created for each agent.
DATAROBOT_DEFAULT_EXECUTION_ENVIRONMENT="[DataRobot] Python 3.11 GenAI Agents" 

agent.pyファイルの修正

ローカルで開発されたエージェント用に生成された最初のファイルは、marketing_crew.pyファイルでした。 このファイルのコードはagent.pyファイル、主にMyAgentクラスに統合する必要があります。 MyAgentクラス以外の変更は、Processクラスをcrewaiライブラリインポートに追加することと、SerperDevToolクラスをcrewai_toolsライブラリから追加することだけです。 以下のコードブロックの内容をコピーし、agent_crewai/custom_model/agent.pyファイルの内容を置き換えます。 元のテンプレートで作成されたagent.pyファイルに対する正確な変更点を確認するには、git diffを使用します。

この基本ステップでのコードのコピー

この基本ステップで、既存のテンプレートを修正するには、大きなコードブロックをコピーする必要があります。 コードスニペットの全内容をコピーするには、スニペットの右上隅にある クリップボードにコピーをクリックします。

agent.py
import json
import os
import re
from typing import Any, Generator, Optional, Union
from urllib.parse import urljoin, urlparse

from crewai import LLM, Agent, Crew, Task, Process
from crewai_tools import SerperDevTool
from crewai_event_listener import CrewAIEventListener
from openai.types.chat import CompletionCreateParams
from ragas import MultiTurnSample
from ragas.messages import AIMessage, HumanMessage, ToolMessage


class MyAgent:
    """MyAgent is a custom marketing crew that uses CrewAI to research, write, and edit marketing content.
    It utilizes DataRobot's LLM Gateway or a specific deployment for language model interactions.
    This example illustrates 3 agents that handle marketing tasks: market research, copywriting, and editing.
    """

    def __init__(
        self,
        api_key: Optional[str] = None,
        api_base: Optional[str] = None,
        model: Optional[str] = None,
        verbose: Optional[Union[bool, str]] = True,
        timeout: Optional[int] = 90,
        **kwargs: Any,
    ):
        """Initializes the MyAgent class with API key, base URL, model, and verbosity settings.

        Args:
            api_key: Optional[str]: API key for authentication with DataRobot services.
                Defaults to None, in which case it will use the DATAROBOT_API_TOKEN environment variable.
            api_base: Optional[str]: Base URL for the DataRobot API.
                Defaults to None, in which case it will use the DATAROBOT_ENDPOINT environment variable.
            model: Optional[str]: The LLM model to use.
                Defaults to None.
            verbose: Optional[Union[bool, str]]: Whether to enable verbose logging.
                Accepts boolean or string values ("true"/"false"). Defaults to True.
            timeout: Optional[int]: How long to wait for the agent to respond.
                Defaults to 90 seconds.
            **kwargs: Any: Additional keyword arguments passed to the agent.
                Contains any parameters received in the CompletionCreateParams.

        Returns:
            None
        """
        self.api_key = api_key or os.environ.get("DATAROBOT_API_TOKEN")
        self.api_base = (
            api_base
            or os.environ.get("DATAROBOT_ENDPOINT")
            or "https://api.datarobot.com"
        )
        self.model = model
        self.timeout = timeout
        if isinstance(verbose, str):
            self.verbose = verbose.lower() == "true"
        elif isinstance(verbose, bool):
            self.verbose = verbose
        self.event_listener = CrewAIEventListener()

        # Load SERPER_API_KEY from runtime parameters if available
        try:
            from datarobot_drum import RuntimeParameters
            serper_key = RuntimeParameters.get("SERPER_API_KEY")
            if serper_key and serper_key != "SET_VIA_PULUMI_OR_MANUALLY":
                os.environ["SERPER_API_KEY"] = serper_key
        except (ValueError, ImportError):
            pass  # Runtime parameters not available in local development

        # Initialize the search tool
        self.search_tool = SerperDevTool()

    @property
    def llm(self) -> LLM:
        """Returns a CrewAI LLM instance configured to use DataRobot's LLM Gateway or a specific deployment.

        For help configuring different LLM backends see:
        https://github.com/datarobot-community/datarobot-agent-templates/blob/main/docs/developing-agents-llm-providers.md
        """
        api_base = urlparse(self.api_base)
        if os.environ.get("LLM_DEPLOYMENT_ID"):
            path = api_base.path
            if "/api/v2/deployments" not in path and "api/v2/genai" not in path:
                # Ensure the API base ends with /api/v2/ for deployments
                if not path.endswith("/"):
                    path += "/"
                if not path.endswith("api/v2/"):
                    path = urljoin(path, "api/v2/")
            api_base = api_base._replace(path=path)
            api_base_str = api_base.geturl()
            deployment_id = os.environ.get("LLM_DEPLOYMENT_ID")
            return LLM(
                model="openai/gpt-4o-mini",
                api_base=f"{api_base_str}deployments/{deployment_id}/",
                api_key=self.api_key,
                timeout=self.timeout,
            )
        else:
            # Use LLM Gateway
            api_base_str = api_base.geturl()
            if api_base_str.endswith("api/v2/"):
                api_base_str = api_base_str[:-7]  # Remove 'api/v2/'
            elif api_base_str.endswith("api/v2"):
                api_base_str = api_base_str[:-6]  # Remove 'api/v2'
            return LLM(
                model="datarobot/azure/gpt-4o-mini",
                api_base=api_base_str,
                api_key=self.api_key,
                timeout=self.timeout,
            )

    @property
    def agent_researcher(self) -> Agent:
        """Market Researcher Agent - finds and analyzes target audience and marketing angles."""
        return Agent(
            role='Senior Market Researcher',
            goal='To find and analyze the target audience and marketing angles for a given product',
            backstory="""You are a seasoned market researcher with a knack for uncovering consumer insights.
            You excel at identifying demographics, psychographics, and the key pain points of a target audience.
            Your analysis forms the foundation of any successful marketing campaign.""",
            verbose=self.verbose,
            allow_delegation=False,
            tools=[self.search_tool],
            llm=self.llm
        )

    @property
    def agent_copywriter(self) -> Agent:
        """Marketing Copywriter Agent - writes compelling and persuasive marketing copy."""
        return Agent(
            role='Expert Marketing Copywriter',
            goal='To write compelling and persuasive marketing copy based on market research',
            backstory="""You are a world-class copywriter, known for your ability to weave words that sell.
            You take research and transform it into captivating headlines, engaging social media posts,
            and persuasive product descriptions. Your copy is clear, concise, and converts.""",
            verbose=self.verbose,
            allow_delegation=False,
            llm=self.llm
        )

    @property
    def agent_editor(self) -> Agent:
        """Review and Editing Specialist Agent - reviews and refines marketing copy."""
        return Agent(
            role='Chief Editor and Marketing Strategist',
            goal='To review and refine marketing copy for clarity, tone, brand alignment, and effectiveness',
            backstory="""You are a meticulous editor with a deep understanding of marketing strategy.
            You have a keen eye for detail and ensure that all copy is not only grammatically perfect
            but also aligns with the brand's voice and strategic goals. You provide the final polish.""",
            verbose=self.verbose,
            allow_delegation=False,
            llm=self.llm
        )

    @property
    def task_research(self) -> Task:
        """Research task - analyzes the product and identifies target audience and USPs."""
        return Task(
            description="""Analyze the provided product: '{product_description}'.
            Identify the primary target audience, their key pain points, and desires.
            Research competitors and identify unique selling propositions (USPs).
            The final output should be a concise report with actionable insights.""",
            expected_output="""A report containing:
            1. Target Audience Profile (demographics, interests, online behavior).
            2. Key Pain Points and Desires of the audience.
            3. A list of 3-5 Unique Selling Propositions (USPs) for the product.
            4. Competitor analysis summary.""",
            agent=self.agent_researcher
        )

    @property
    def task_copywriting(self) -> Task:
        """Copywriting task - writes three distinct pieces of marketing copy."""
        return Task(
            description="""Using the market research report, write three distinct pieces of marketing copy for the product: '{product_description}'.
            The copy should be tailored to the identified target audience.
            The pieces are:
            1. A catchy Facebook ad post (approx. 50-80 words).
            2. An engaging email subject line and a short preview text.
            3. A persuasive product description for an e-commerce website (approx. 100-150 words).""",
            expected_output="""A document with three sections:
            1. Facebook Ad Copy.
            2. Email Subject Line and Preview.
            3. E-commerce Product Description.""",
            agent=self.agent_copywriter,
            context=[self.task_research]
        )

    @property
    def task_review(self) -> Task:
        """Review task - reviews and refines the marketing copy."""
        return Task(
            description="""Review the marketing copy provided. Check for grammatical errors, clarity, and brand voice alignment.
            Ensure the copy is persuasive and directly addresses the target audience's pain points identified in the research.
            Provide a final, polished version of all three copy pieces with constructive feedback.""",
            expected_output="""The final, production-ready marketing copy for all three formats,
            along with a brief note on any significant changes made and why.""",
            agent=self.agent_editor,
            context=[self.task_copywriting]
        )

    def crew(self) -> Crew:
        """Creates the marketing crew with all agents and tasks."""
        return Crew(
            agents=[self.agent_researcher, self.agent_copywriter, self.agent_editor],
            tasks=[self.task_research, self.task_copywriting, self.task_review],
            process=Process.sequential,
            verbose=self.verbose
        )

    async def invoke(
        self, completion_create_params: CompletionCreateParams
    ) -> Union[
        Generator[tuple[str, Any | None, dict[str, int]], None, None],
        tuple[str, Any | None, dict[str, int]],
    ]:
        """Run the marketing crew with the provided completion parameters.

        [THIS METHOD IS REQUIRED FOR THE AGENT TO WORK WITH DRUM SERVER]

        Args:
            completion_create_params: The completion request parameters including input product description and settings.
        Returns:
            Union[
                Generator[tuple[str, Any | None, dict[str, int]], None, None],
                tuple[str, Any | None, dict[str, int]],
            ]: For streaming requests, returns a generator yielding tuples of (response_text, pipeline_interactions, usage_metrics).
               For non-streaming requests, returns a single tuple of (response_text, pipeline_interactions, usage_metrics).
        """
        # Retrieve the starting user prompt from the CompletionCreateParams
        user_messages = [
            msg
            for msg in completion_create_params["messages"]
            # You can use other roles as needed (e.g. "system", "assistant")
            if msg.get("role") == "user"
        ]
        user_prompt: Any = user_messages[0] if user_messages else {}
        user_prompt_content = user_prompt.get("content", "")

        # Handle both string and dict inputs
        if isinstance(user_prompt_content, str):
            try:
                inputs = json.loads(user_prompt_content)
                if isinstance(inputs, dict) and "product_description" not in inputs:
                    # If it's a dict but doesn't have product_description, use the first value
                    if inputs:
                        inputs = {"product_description": list(inputs.values())[0]}
                    else:
                        inputs = {"product_description": ""}
                elif not isinstance(inputs, dict):
                    inputs = {"product_description": inputs}
            except json.JSONDecodeError:
                inputs = {"product_description": user_prompt_content}
        else:
            inputs = {"product_description": str(user_prompt_content)}

        # Print commands may need flush=True to ensure they are displayed in real-time.
        print("Running marketing crew with inputs:", inputs, flush=True)

        # Run the crew with the inputs
        crew_output = self.crew().kickoff(inputs=inputs)

        # Extract the response text from the crew output
        response_text = str(crew_output.raw)

        # Create a list of events from the event listener
        events = self.event_listener.messages
        if len(events) > 0:
            last_message = events[-1].content
            if last_message != response_text:
                events.append(AIMessage(content=response_text))
        else:
            events = None

        pipeline_interactions = self.create_pipeline_interactions_from_events(events)

        usage_metrics = {
            "completion_tokens": crew_output.token_usage.completion_tokens,
            "prompt_tokens": crew_output.token_usage.prompt_tokens,
            "total_tokens": crew_output.token_usage.total_tokens,
        }

        return response_text, pipeline_interactions, usage_metrics

    @staticmethod
    def create_pipeline_interactions_from_events(
        events: list[Union[HumanMessage, AIMessage, ToolMessage]],
    ) -> MultiTurnSample | None:
        """Convert a list of events into a MultiTurnSample.

        Creates the pipeline interactions for moderations and evaluation
        (e.g. Task Adherence, Agent Goal Accuracy, Tool Call Accuracy)
        """
        if not events:
            return None
        return MultiTurnSample(user_input=events) 

model-metadata.yamlファイルの修正

このエージェントをローカルで使用するのにこの手順は必要ありませんが、エージェントのプレイグラウンドや本番環境で使用するために既存のmodel-metadata.yamlファイルを修正することは重要です。 SERPER_API_KEYは、DataRobotの資格情報管理を使用して保存する必要があります。

model-metadata.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
---
name: agent_crewai
type: inference
targetType: agenticworkflow
runtimeParameterDefinitions:
  - fieldName: LLM_DEPLOYMENT_ID
    defaultValue: <YOUR_LLM_DEPLOYMENT_ID>
    type: string
  - fieldName: SERPER_API_KEY
    defaultValue: <YOUR_SEARCH_TOOL_CREDENTIAL_ID>
    type: credential 

Access request headers in your agent

When your agent is deployed and receives requests, you can access HTTP headers passed from the client. This is useful for authentication, tracking metadata, or implementing custom business logic based on request context.

機能に関する注意事項
  • プレフィックスが X-Untrusted-*のヘッダーのみがエージェントに渡されます。
  • ディクショナリからアクセスする場合、ヘッダーの英大文字と英小文字は区別されます。
  • オプションのヘッダーにアクセスする際は、必ずNoneの有無を確認するか、デフォルト値を指定します。

Headers with the X-Untrusted-* prefix are made available through the chat() function's **kwargs parameter in the custom.py file. Here's how to extract and use them:

from datarobot_genai.core.chat import initialize_authorization_context

def chat(
    completion_create_params: CompletionCreateParams
    | CompletionCreateParamsNonStreaming
    | CompletionCreateParamsStreaming,
    model: str,
    **kwargs,
) -> Union[CustomModelChatResponse, Iterator[CustomModelStreamingResponse]]:
    # Extract all headers from kwargs
    headers = kwargs.get("headers", {})

    # Access specific X-Untrusted-* headers
    authorization_header = headers.get("X-Untrusted-Authorization")
    request_id = headers.get("X-Untrusted-Request-ID")

    # Use headers in your agent logic
    if authorization_header:
        # Pass to downstream services or tools
        print(f"Processing request with auth: {authorization_header}")

    # Continue with normal agent execution
    initialize_authorization_context(completion_create_params, **kwargs)
    agent = MyAgent(**completion_create_params)
    # ... 
一般的なユースケース
  • 外部認証:外部APIまたはツールにX-Untrusted-Authorizationヘッダーを渡す。
  • リクエストの追跡:ロギングとデバッグにX-Untrusted-Request-IDを使用する。
  • 条件付きロジックX-Untrusted-RegionX-Untrusted-User-Type、またはその他のカスタムヘッダーに基づいてエージェントの動作を調整する。

For more information, see the accessing request headers section in the troubleshooting guide.

修正されたエージェントワークフローのテスト

agent_crewai/custom_modelディレクトリ内のエージェントワークフローカスタムモデルに必要な変更と追加をすべて行ったら、以下のコマンドでワークフローをテストします。

task agent:cli START_DEV=1 -- execute --user_prompt "A revolutionary AI-powered fitness tracker that monitors your health" 

トラブルシューティング

エージェントワークフローのテスト中に問題が発生した場合は、エージェントの環境と依存関係を更新することをお勧めします。 これを行うには、task install(またはtask setup)、task agent:install、およびtask agent:updateコマンドを使用します。 これらのコマンドやその他のコマンドの詳細については、taskコマンドを使用してください。

テスト中に接続エラーが表示された場合は、コマンドでSTART_DEV=1を使用していることを確認するか、別のターミナルウィンドウでtask agent:devを使用して開発サーバーを個別に起動します。

次のステップ

マーケティングコピーを作成するための更新されたエージェントワークフローのテストに問題がなければ、ワークフローをワークショップに送信してエージェントのプレイグラウンドに接続するか、ワークフローをデプロイします。