From 60ad5a3e7056f39527ac7b9d6fd562701adcd756 Mon Sep 17 00:00:00 2001 From: Harrison Chase Date: Tue, 19 Aug 2025 14:56:30 -0700 Subject: [PATCH] add recruiter example --- examples/recruiter/langgraph.json | 7 +++ examples/recruiter/recruiter_agent.py | 73 +++++++++++++++++++++++++++ examples/recruiter/requirements.txt | 3 ++ src/deepagents/sub_agent.py | 2 +- 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 examples/recruiter/langgraph.json create mode 100644 examples/recruiter/recruiter_agent.py create mode 100644 examples/recruiter/requirements.txt diff --git a/examples/recruiter/langgraph.json b/examples/recruiter/langgraph.json new file mode 100644 index 00000000..4d2c759d --- /dev/null +++ b/examples/recruiter/langgraph.json @@ -0,0 +1,7 @@ +{ + "dependencies": ["."], + "graphs": { + "research": "./recruiter_agent.py:create_agent" + }, + "env": ".env" +} \ No newline at end of file diff --git a/examples/recruiter/recruiter_agent.py b/examples/recruiter/recruiter_agent.py new file mode 100644 index 00000000..331a3103 --- /dev/null +++ b/examples/recruiter/recruiter_agent.py @@ -0,0 +1,73 @@ +import os + +from exa_py import Exa + +from deepagents import create_deep_agent, SubAgent + +exa = Exa(api_key = os.environ['EXA_API_KEY']) + + + + + + +# Search tool to use to do research +def linkedin_search( + query: str, + num_results: int = 5, +): + """Run a linkedin search""" + return exa.search_and_contents( + query, + text=True, + num_results=num_results, + type="auto", + category="linkedin profile" + ) + + +sub_research_prompt = """You are a dedicated researcher. Your job is to source candidates for the role described. + +Write down any new candidates in candidates.json + +only include candidates if they look good + +Respond to the user saying how many candidates you wrote down.""" + +research_sub_agent = { + "name": "research-agent", + "description": "Used to kick off in depth searches. Give it a brief to research.", + "prompt": sub_research_prompt, + "tools": ["linkedin_search"] +} + +# Prompt prefix to steer the agent to be an expert researcher +research_instructions = """You are an expert sourcer + +Use the research agent to run specific searches. It will write its results to candidates.json""" + +# Create the agent +agent = create_deep_agent( + [linkedin_search], + research_instructions, + subagents=[research_sub_agent], +).with_config({"recursion_limit": 1000}) + +from pydantic import BaseModel + +class Config(BaseModel): + instructions: str = research_instructions + subagents: list[SubAgent] = [research_sub_agent] + +from langchain_core.runnables import RunnableConfig + +def create_agent(config: RunnableConfig): + config = config.get('configurable', {}) + config_fields = {k: v for k,v in config.items() if k in ['instructions', 'subagents']} + config = Config(**config_fields) + return create_deep_agent( + [linkedin_search], + config.instructions, + subagents=config.subagents, + config_schema=Config, + ).with_config({"recursion_limit": 1000}) diff --git a/examples/recruiter/requirements.txt b/examples/recruiter/requirements.txt new file mode 100644 index 00000000..a26d50c4 --- /dev/null +++ b/examples/recruiter/requirements.txt @@ -0,0 +1,3 @@ +deepagents +langgraph-cli[inmem] +exa-py diff --git a/src/deepagents/sub_agent.py b/src/deepagents/sub_agent.py index c8bb5793..7c289565 100644 --- a/src/deepagents/sub_agent.py +++ b/src/deepagents/sub_agent.py @@ -2,7 +2,7 @@ from deepagents.state import DeepAgentState from langgraph.prebuilt import create_react_agent from langchain_core.tools import BaseTool -from typing import TypedDict +from typing_extensions import TypedDict from langchain_core.tools import tool, InjectedToolCallId from langchain_core.messages import ToolMessage from typing import Annotated, NotRequired