Skills MCP Model 博客 提交 Skills

DeepSeek Agent Development Tutorial

Build intelligent Agents from scratch. Master ReAct reasoning patterns, Function Calling tool invocation, multi-Agent collaboration, memory management, planning and execution. Complete Python code, ready to use.

Start Learning

What is an AI Agent? Why do we need it?

An AI Agent is an AI system that can autonomously perceive its environment, make plans, call tools, and execute tasks. Unlike traditional Chatbots, Agents do not just answer questions but can actively think and act to complete complex workflows.

Agent Overview

Understanding the core concepts, architecture components, and essential differences between AI Agents and traditional Chatbots is the theoretical foundation for building intelligent agents.

Agent vs Traditional Chatbot

Comparison Dimension Traditional Chatbot AI Agent
Interaction Mode Single-turn Q&A, one question one answer Multi-step reasoning, autonomously executes task chains
Capability Boundary Only generates text based on training data Can call external tools, APIs, databases
Memory Capability Temporary memory within context window Short-term memory + long-term memory (vector storage)
Task Complexity Simple conversation, information retrieval Multi-step tasks, workflow automation
Typical Scenarios Customer service Q&A, chit-chat, content generation Data analysis, automated reports, code execution, process orchestration

Four Core Components of Agent

Component English Function Technical Implementation
Large Language Model LLM The brain of the Agent, responsible for reasoning and decision-making DeepSeek-Chat / DeepSeek-Reasoner
Tools Tools The hands and feet of the Agent, executing specific operations Function Calling / API / Code Executor
Memory Memory Stores and retrieves historical information Conversation history / Vector database / Knowledge graph
Planning Planning Decomposes tasks, formulates execution strategies ReAct / Plan-and-Execute / Tree-of-Thought

Agent Workflow

  1. Perception: Receive user input, understand task intent and goals
  2. Thinking: Analyze the task, formulate an execution plan, decide next actions
  3. Action: Call tools to execute specific operations (search, calculation, API calls, etc.)
  4. Observation: Obtain tool execution results, evaluate whether the goal is achieved
  5. Loop: Decide whether to continue execution or output the final answer based on observations

This "Thinking-Action-Observation" loop is the core working pattern of an Agent. For more basic knowledge about DeepSeek models, please see DeepSeek Model Architecture Details.

ReAct Mode

ReAct (Reasoning + Acting) is the core reasoning mode of an Agent. It alternates reasoning and acting, allowing the model to call tools while thinking and verify reasoning through actions.

ReAct Loop: Thought - Action - Observation

Step Description Example
Thought Analyze the current state and decide what to do next "I need to check today's weather, then decide whether to suggest bringing an umbrella"
Action Execute a specific tool call Call the get_weather("Beijing") function
Observation Get the tool result and evaluate whether the task is complete "Beijing is sunny today, 25 degrees, no need for an umbrella"

DeepSeek + ReAct Complete Implementation

The following code shows a complete ReAct Agent that uses the DeepSeek model for reasoning and calls search and calculation tools:

"""DeepSeek ReAct Agent — Complete Implementation""" import json import re from openai import OpenAI client = OpenAI( api_key="sk-your-api-key", base_url="https://api.deepseek.com/v1", ) # ========== Tool Definitions ========== def search_web(query: str) -> str: """Simulate a search engine, return query results""" # Replace with a real search API in production mock_results = { "Beijing weather": "Beijing is sunny today, 22-28 degrees, good air quality", "DeepSeek": "DeepSeek is a large language model developed by DeepSeek, supporting 1M context", } return mock_results.get(query, f"No information found about '{query}'") def calculate(expression: str) -> str: """Safe math calculator""" try: # Only allow numbers and basic operators if not re.match(r'^[\d\+\-\*\/\(\)\.\s]+$', expression): return "Error: Expression contains illegal characters" result = eval(expression) return str(result) except Exception as e: return f"Calculation error: {e}" # Tool registry TOOLS = { "search": search_web, "calculate": calculate, } # ========== ReAct Prompt ========== REACT_SYSTEM_PROMPT = """You are an intelligent Agent that can use tools. Please answer strictly in the ReAct format. Available tools: - search(query): Search the internet for information - calculate(expression): Perform mathematical calculations Answer format (must strictly follow): Thought: Your thoughts and analysis of the current situation Action: The operation to execute, in the format tool_name(arg) Observation: The result of the tool execution ... (repeat Thought/Action/Observation until you have the answer) Thought: I have enough information to answer Final Answer: The final answer Note: Only execute one Action at a time, wait for Observation before continuing.""" # ========== ReAct Loop ========== def react_agent(user_query: str, max_steps: int = 5): """ReAct Agent main loop""" messages = [ {"role": "system", "content": REACT_SYSTEM_PROMPT}, {"role": "user", "content": user_query}, ] for step in range(max_steps): print(f"\n--- Step {step + 1} ---") # Call DeepSeek model response = client.chat.completions.create( model="deepseek-chat", messages=messages, temperature=0.1, ) reply = response.choices[0].message.content print(reply) messages.append({"role": "assistant", "content": reply}) # Check if it's the final answer if "Final Answer:" in reply: final = reply.split("Final Answer:")[-1].strip() return final # Parse Action action_match = re.search(r'Action:\s*(\w+)\(([^)]*)\)', reply) if action_match: tool_name = action_match.group(1) tool_arg = action_match.group(2).strip().strip('"').strip("'") if tool_name in TOOLS: observation = TOOLS[tool_name](tool_arg) print(f"Observation: {observation}") messages.append({ "role": "user", "content": f"Observation: {observation}", }) else: messages.append({ "role": "user", "content": f"Error: Unknown tool '{tool_name}'", }) return "Maximum step limit reached, failed to complete the task." # ========== Run Test ========== if __name__ == "__main__": query = "What's the weather like in Beijing today? If the temperature exceeds 25 degrees, help me calculate how many bottles are needed for 30 people each needing 2 bottles, total?" result = react_agent(query) print(f"\n{'='*60}\nFinal Answer: {result}\n{'='*60}")

Key Points of ReAct Mode

  • Execute only one Action at a time, wait for Observation before continuing
  • Thought and Action must strictly follow the format for easy regex parsing
  • Set max_steps to prevent infinite loops, usually 5-10 steps is enough
  • Tool functions need proper error handling and return meaningful results
  • DeepSeek's reasoning ability is very suitable for ReAct mode

Function Calling Tool Invocation

DeepSeek supports native Function Calling capability, allowing the model to automatically identify when to call tools and generate structured function call parameters. This is more reliable and efficient than manually parsing the ReAct format.

Define Tool Schema

Define tools using the OpenAI-compatible Function Calling format:

from openai import OpenAI import json client = OpenAI( api_key="sk-your-api-key", base_url="https://api.deepseek.com/v1", ) # Define tool schema (OpenAI Function Calling format) tools = [ { "type": "function", "function": { "name": "get_weather", "description": "Get real-time weather information for a specified city", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "City name, e.g., Beijing, Shanghai, Tokyo", }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "Temperature unit, default is celsius", }, }, "required": ["city"], }, }, }, { "type": "function", "function": { "name": "search_database", "description": "Search for information in the internal knowledge base", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "Search keyword or question", }, "top_k": { "type": "integer", "description": "Number of results to return, default 3", "default": 3, }, }, "required": ["query"], }, }, }, { "type": "function", "function": { "name": "send_email", "description": "Send an email", "parameters": { "type": "object", "properties": { "to": {"type": "string", "description": "Recipient email address"}, "subject": {"type": "string", "description": "Email subject"}, "body": {"type": "string", "description": "Email body content"}, }, "required": ["to", "subject", "body"], }, }, }, ]

Function Calling Agent Main Loop

# Tool implementation def get_weather(city: str, unit: str = "celsius") -> dict: """Simulated weather query (replace with real API in production)""" return { "city": city, "temperature": 26, "condition": "Sunny", "humidity": "45%", "unit": unit, } def search_database(query: str, top_k: int = 3) -> dict: return {"query": query, "results": [f"Result{i+1}: Information about {query}" for i in range(top_k)]} def send_email(to: str, subject: str, body: str) -> dict: return {"status": "sent", "to": to, "subject": subject} # Tool mapping table AVAILABLE_FUNCTIONS = { "get_weather": get_weather, "search_database": search_database, "send_email": send_email, } # ========== Function Calling Agent ========== def function_calling_agent(user_query: str, max_turns: int = 5): messages = [ {"role": "system", "content": "You are an intelligent assistant that can use tools to complete tasks. Please answer in Chinese."}, {"role": "user", "content": user_query}, ] for turn in range(max_turns): response = client.chat.completions.create( model="deepseek-chat", messages=messages, tools=tools, tool_choice="auto", # Model automatically decides whether to call tools ) assistant_message = response.choices[0].message # If model calls tools if assistant_message.tool_calls: messages.append(assistant_message) for tool_call in assistant_message.tool_calls: func_name = tool_call.function.name func_args = json.loads(tool_call.function.arguments) print(f"[Calling tool] {func_name}({func_args})") if func_name in AVAILABLE_FUNCTIONS: result = AVAILABLE_FUNCTIONS[func_name](**func_args) else: result = {"error": f"Unknown tool: {func_name}"} print(f"[Tool result] {result}") # Add tool result to conversation messages.append({ "role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(result, ensure_ascii=False), }) else: # Model returns answer directly return assistant_message.content return "Reached maximum round limit." # Test result = function_calling_agent("Query Beijing weather, then send a weather report to admin@company.com") print(f"\nFinal result:\n{result}")

Advantages of Function Calling

  • The model automatically decides when to call tools, no need to manually parse formats
  • Parameters are passed as structured JSON, avoiding regex parsing errors
  • Supports parallel calling of multiple tools (set tool_choice to "auto")
  • DeepSeek API is fully compatible with OpenAI Function Calling format
  • Can be used in a mixed way: the model can call tools and generate text simultaneously in one response

LangChain Agent Integration

LangChain provides high-level Agent abstractions that encapsulate the ReAct loop and tool management. Using LangChain makes Agent development more concise and maintainable, while supporting multiple Agent types and tool combinations.

Install Dependencies

pip install langchain langchain-openai langchain-community

Create LangChain Agent

from langchain_openai import ChatOpenAI from langchain.agents import create_react_agent, AgentExecutor from langchain.tools import Tool from langchain.prompts import PromptTemplate from langchain_community.tools import WikipediaQueryRun from langchain_community.utilities import WikipediaAPIWrapper import requests # Initialize DeepSeek model llm = ChatOpenAI( model="deepseek-chat", base_url="https://api.deepseek.com/v1", api_key="sk-your-api-key", temperature=0.1, ) # ========== Custom Tool Development ========== # Tool 1: Exchange Rate Query def get_exchange_rate(currency_pair: str) -> str: """Query real-time exchange rate. Input format: USD/CNY or EUR/USD""" try: base, target = currency_pair.split("/") url = f"https://api.exchangerate-api.com/v4/latest/{base}" data = requests.get(url, timeout=5).json() rate = data["rates"][target] return f"1 {base} = {rate} {target}" except Exception as e: return f"Exchange rate query failed: {e}" # Tool 2: File Reading def read_file(filepath: str) -> str: """Read local file content""" try: with open(filepath, "r", encoding="utf-8") as f: content = f.read() if len(content) > 2000: return content[:2000] + "\n... (content too long, truncated)" return content except Exception as e: return f"Failed to read file: {e}" # Tool 3: Python Code Execution def execute_python(code: str) -> str: """Safely execute Python code and return the result""" # Note: In production, use a sandbox environment (e.g., Docker) import io, sys old_stdout = sys.stdout sys.stdout = buffer = io.StringIO() try: exec(code, {"__builtins__": { "print": print, "range": range, "len": len, "int": int, "str": str, "list": list, "dict": dict, "sum": sum, "sorted": sorted, "enumerate": enumerate, }}) result = buffer.getvalue() return result.strip() if result.strip() else "Code executed successfully (no output)" except Exception as e: return f"Execution error: {e}" finally: sys.stdout = old_stdout # ========== Register Tools ========== tools = [ Tool( name="Exchange Rate Query", func=get_exchange_rate, description="Query real-time exchange rates. Input format: USD/CNY or EUR/USD", ), Tool( name="File Reading", func=read_file, description="Read local file content. Input is the file path", ), Tool( name="Python Execution", func=execute_python, description="Execute Python code and return the result. Input is a Python code string", ), Tool( name="Wikipedia", func=WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper(lang="zh")).run, description="Search Chinese Wikipedia. Input is the search keyword", ), ] # ReAct Prompt Template prompt = PromptTemplate.from_template("""You are an intelligent assistant that can use the following tools to complete tasks: {tools} Use the following format to answer: Question: the user's question Thought: think about what to do next Action: tool name Action Input: tool input parameters Observation: tool return result ... (can repeat Thought/Action/Action Input/Observation) Thought: I now have enough information Final Answer: final answer Begin! Question: {input} Thought: {agent_scratchpad}""") # Create Agent and Executor agent = create_react_agent(llm=llm, tools=tools, prompt=prompt) agent_executor = AgentExecutor( agent=agent, tools=tools, verbose=True, # Print detailed execution process handle_parsing_errors=True, # Automatically handle format errors max_iterations=8, # Maximum number of iterations ) # Run Agent result = agent_executor.invoke({ "input": "Query USD/CNY exchange rate, then calculate how many RMB 1000 USD can be exchanged for", }) print(f"\nFinal answer: {result['output']}")

AgentExecutor Parameter Description

Parameter Description Recommended Value
verbose Whether to print detailed execution process True during development, False in production
handle_parsing_errors Automatically handle model output format errors True
max_iterations Maximum number of iterations to prevent infinite loops 5-10
early_stopping_method Handling method after reaching maximum iterations "generate" (generate final answer)

Multi-Agent Collaboration

A single Agent has limited capabilities; complex tasks require multiple Agents to collaborate with division of labor. CrewAI is currently the most popular multi-agent framework, supporting the definition of Agents with different roles and collaboration in a process to complete tasks.

CrewAI Multi-Agent Architecture

  • Agent: Defines role, goal, backstory, and available tools
  • Task: Defines the specific work to be done, including description, expected output, and assigned Agent
  • Crew: Organizes multiple Agents to collaborate sequentially or hierarchically to complete a set of tasks
  • Process: Controls the execution order of tasks, supporting sequential and hierarchical

CrewAI Complete Example

# pip install crewai crewai-tools from crewai import Agent, Task, Crew, Process from crewai import LLM # Configure DeepSeek as the underlying model deepseek_llm = LLM( model="deepseek/deepseek-chat", base_url="https://api.deepseek.com/v1", api_key="sk-your-api-key", ) # ========== Define Agent Roles ========== # Researcher: responsible for information collection and analysis researcher = Agent( role="Senior Researcher", goal="Conduct in-depth research on the specified topic, collect comprehensive and accurate information and data", backstory="""You are an experienced research analyst who has worked at a top consulting firm for 10 years. You excel at quickly gathering information, identifying key trends, and supporting viewpoints with data. Your reports are always well-structured and well-argued.""", llm=deepseek_llm, verbose=True, allow_delegation=False, ) # Writer: responsible for content creation writer = Agent( role="Senior Content Writer", goal="Write engaging, professional, and accurate content based on research materials", backstory="""You are a senior technology writer who has contributed to several well-known tech media outlets. You excel at transforming complex technical concepts into accessible articles. Your articles are logically clear, data-accurate, and highly readable.""", llm=deepseek_llm, verbose=True, allow_delegation=False, ) # Reviewer: responsible for quality control reviewer = Agent( role="Content Reviewer", goal="Review the accuracy, readability, and professionalism of content to ensure output quality", backstory="""You are a senior editor who has worked at a top publishing house for 15 years. You have extremely high standards for text and can spot the slightest errors. Your review criteria include: factual accuracy, logical coherence, language expression, and formatting.""", llm=deepseek_llm, verbose=True, allow_delegation=False, ) # ========== Define Tasks ========== research_task = Task( description="""Research the latest developments in DeepSeek Agent development, including: 1. DeepSeek API's Function Calling capabilities 2. Integration methods of LangChain and CrewAI with DeepSeek 3. Best practices for Agents in production environments 4. Comparison of Agent capabilities with other LLMs (GPT-4, Claude) Please provide detailed data and specific technical details.""", expected_output="A structured research report containing key findings, technical comparisons, and best practice recommendations, no less than 500 words", agent=researcher, ) writing_task = Task( description="""Based on the research report, write an introductory article for developers on DeepSeek Agent development. Requirements: 1. Language should be easy to understand, suitable for developers with basic Python knowledge 2. Include specific code examples and architecture diagram descriptions 3. Highlight DeepSeek's unique advantages 4. Keep the length between 800-1000 words""", expected_output="A complete, ready-to-publish technical article", agent=writer, ) review_task = Task( description="""Review the quality of the article, checking: 1. Whether technical details are accurate 2. Whether code examples are runnable 3. Whether logic is clear and coherent 4. Whether language expression is professional If there are issues, mark the specific locations and provide suggestions for improvement.""", expected_output="Review report, including pass/fail determination and specific modification suggestions", agent=reviewer, ) # ========== Assemble Crew and Execute ========== crew = Crew( agents=[researcher, writer, reviewer], tasks=[research_task, writing_task, review_task], process=Process.sequential, # Sequential execution verbose=True, ) result = crew.kickoff() print("\n=== Final Output ===\n", result)

Best Practices for Multi-Agent Collaboration

  • Each Agent should only be responsible for one clear role to avoid overlapping responsibilities
  • Task descriptions should be specific, including a clear expected_output format
  • Research agents can be configured with search tools, and execution agents can be configured with code tools
  • Hierarchical process is suitable for complex projects, but requires an additional manager Agent
  • Set allow_delegation=False to prevent Agents from shifting tasks to each other

Agent Memory Management

Memory is the key capability that distinguishes Agents from ordinary Chatbots. Proper memory management allows Agents to remember historical conversations, user preferences, and long-term knowledge, thereby providing a more personalized and coherent interactive experience.

Three Types of Memory

Memory Type Storage Method Lifecycle Applicable Scenarios
Short-term Memory Message list (context window) Single session Current conversation context, multi-turn interactions
Long-term Memory Vector database / Knowledge graph Persistent across sessions User preferences, historical knowledge, project background
Working Memory Structured data storage Single task Intermediate task results, execution status

Short-term Memory: Conversation History Management

from langchain.memory import ConversationBufferWindowMemory, ConversationSummaryMemory from langchain_openai import ChatOpenAI llm = ChatOpenAI( model="deepseek-chat", base_url="https://api.deepseek.com/v1", api_key="sk-your-api-key", ) # Method 1: Sliding window memory — only keep the most recent K rounds of conversation window_memory = ConversationBufferWindowMemory( k=5, # Only keep the most recent 5 rounds return_messages=True, memory_key="chat_history", ) # Method 2: Summary memory — use LLM to automatically summarize historical conversations summary_memory = ConversationSummaryMemory( llm=llm, max_token_limit=500, # Summary up to 500 tokens return_messages=True, memory_key="chat_history", ) # Agent using memory from langchain.agents import create_react_agent, AgentExecutor agent = create_react_agent(llm=llm, tools=tools, prompt=prompt) agent_with_memory = AgentExecutor( agent=agent, tools=tools, memory=window_memory, # Inject memory verbose=True, )

Long-term Memory: Vector Store Implementation

from langchain_community.vectorstores import Chroma from langchain_community.embeddings import HuggingFaceEmbeddings from langchain.schema import Document import json, os, time # Initialize vector store embeddings = HuggingFaceEmbeddings( model_name="BAAI/bge-small-zh-v1.5", model_kwargs={"device": "cpu"}, ) vectorstore = Chroma( persist_directory="./agent_memory", embedding_function=embeddings, collection_name="long_term_memory", ) class LongTermMemory: """Long-term memory manager""" def save_memory(self, content: str, metadata: dict = None): """Save a memory""" doc = Document( page_content=content, metadata=metadata or {"timestamp": time.time()}, ) vectorstore.add_documents([doc]) print(f"Saved memory: {content[:50]}...") def recall_memory(self, query: str, k: int = 3) -> str: """Retrieve relevant memories""" docs = vectorstore.similarity_search(query, k=k) if not docs: return "No relevant historical memory" memories = [f"- {d.page_content}" for d in docs] return "\n".join(memories) def clear_memory(self): """Clear all memories""" vectorstore.delete_collection() print("All memories cleared") # Usage example memory = LongTermMemory() memory.save_memory("User preference: prefers concise answer style, not too many technical details") memory.save_memory("Project background: developing an e-commerce recommendation system using DeepSeek as the core engine") relevant = memory.recall_memory("user's answer style preference") print(f"Relevant memories:\n{relevant}")

Hybrid Memory Architecture

Recommended memory architecture combination:

  • Short-term memory: Use ConversationBufferWindowMemory (k=10) to retain recent conversations
  • Long-term memory: Use ChromaDB vector store to store user preferences and project knowledge
  • Working memory: Use Python dictionary to pass intermediate results within a single task
  • Memory retrieval: Automatically retrieve relevant long-term memories before each conversation and inject them into the System Prompt

Planning and Execution

For complex tasks, an Agent needs to first decompose the task into executable subtasks, then execute them step by step. The Plan-and-Execute pattern separates planning and execution, enabling the Agent to handle more complex multi-step tasks.

Plan-and-Execute Pattern

  1. Plan (Planning Phase): The LLM analyzes the task and generates a detailed execution plan (list of steps)
  2. Execute (Execution Phase): The Agent executes step by step according to the plan, observing results at each step
  3. Replan (Replanning): If a step fails or the result does not meet expectations, dynamically adjust the subsequent plan
  4. Finalize (Completion): Aggregate the results of all steps and output the final answer

Complete Plan-and-Execute Implementation

"""DeepSeek Plan-and-Execute Agent""" from openai import OpenAI import json client = OpenAI( api_key="sk-your-api-key", base_url="https://api.deepseek.com/v1", ) # ========== Planning Phase ========== PLANNER_PROMPT = """You are a task planning expert. Please decompose the user's task into clear execution steps. Requirements: 1. Each step should be an atomic operation, not further divisible 2. There should be clear dependencies between steps 3. Consider possible exceptions and alternative plans 4. Output in JSON format Output format: { "task": "original task description", "steps": [ {"id": 1, "description": "step description", "depends_on": [], "expected_output": "expected output"}, {"id": 2, "description": "step description", "depends_on": [1], "expected_output": "expected output"} ] }""" def create_plan(task: str) -> dict: """Generate execution plan""" response = client.chat.completions.create( model="deepseek-chat", messages=[ {"role": "system", "content": PLANNER_PROMPT}, {"role": "user", "content": f"Please create an execution plan for the following task:\n{task}"}, ], temperature=0.1, ) content = response.choices[0].message.content # Extract JSON if "```json" in content: content = content.split("```json")[1].split("```")[0] return json.loads(content) # ========== Execution Phase ========== EXECUTOR_PROMPT = """You are a task execution expert. Please execute the current step and return the result. The complete plan for the current task: {plan} Historical execution results: {history} Current step: Step {step_id}: {step_description} Please execute this step and return the result. If the step fails, explain the reason.""" def execute_step(plan: dict, step: dict, history: list) -> str: """Execute a single step""" response = client.chat.completions.create( model="deepseek-chat", messages=[ {"role": "system", "content": EXECUTOR_PROMPT.format( plan=json.dumps(plan, ensure_ascii=False, indent=2), history=json.dumps(history, ensure_ascii=False, indent=2) if history else "None", step_id=step["id"], step_description=step["description"], )}, ], temperature=0.1, ) return response.choices[0].message.content # ========== Main Loop ========== def plan_and_execute(task: str): """Plan-and-Execute main function""" print("=" * 60) print(f"Task: {task}") # Phase 1: Planning print("\n[Planning Phase] Analyzing task...") plan = create_plan(task) print(f"Generated {len(plan['steps'])} execution steps:") for s in plan["steps"]: print(f" Step {s['id']}: {s['description']}") # Phase 2: Execution print("\n[Execution Phase] Starting execution...") history = [] for step in plan["steps"]: print(f"\n--- Executing step {step['id']}: {step['description']} ---") result = execute_step(plan, step, history) print(f"Result: {result[:200]}...") history.append({ "step_id": step["id"], "description": step["description"], "result": result, "status": "success" if "失败" not in result else "failed", }) # Phase 3: Summary print("\n[Summary Phase] Generating final report...") return history # Test result = plan_and_execute("Analyze DeepSeek API pricing strategy and write a competitive comparison report") print(f"\nExecution completed, total {len(result)} steps completed")

Dynamic Plan Adjustment

When a step fails, you can have the Agent re-plan the remaining steps. After execute_step returns failure, call create_plan with the history of completed steps to let the model generate a new execution plan. This adaptive capability is a hallmark of advanced Agents.

RAG Agent

RAG Agent combines retrieval-augmented generation (RAG) with the agent's tool-calling capabilities, allowing the agent to both retrieve information from a knowledge base and call external tools. This is the most common architecture pattern for enterprise-grade agents.

RAG Agent Architecture

RAG Agent integrates two capabilities:

  • Knowledge Retrieval: Retrieve relevant documents from a vector database to provide accurate contextual information
  • Tool Calling: Call external APIs, execute code, query databases, and more
  • Hybrid Decision-Making: The agent autonomously determines whether to retrieve from the knowledge base or call a tool

Complete RAG Agent Implementation

from langchain_openai import ChatOpenAI from langchain.agents import create_react_agent, AgentExecutor from langchain.tools import Tool from langchain_community.vectorstores import Chroma from langchain_community.embeddings import HuggingFaceEmbeddings from langchain.prompts import PromptTemplate llm = ChatOpenAI( model="deepseek-chat", base_url="https://api.deepseek.com/v1", api_key="sk-your-api-key", temperature=0.1, ) # ========== Initialize knowledge base (vector retrieval tool) ========== embeddings = HuggingFaceEmbeddings( model_name="BAAI/bge-small-zh-v1.5", model_kwargs={"device": "cpu"}, ) vectorstore = Chroma( persist_directory="./chroma_db", embedding_function=embeddings, ) def search_knowledge_base(query: str) -> str: """Search for relevant information in the knowledge base""" docs = vectorstore.similarity_search(query, k=3) if not docs: return "No relevant information found in the knowledge base" results = [] for i, doc in enumerate(docs): source = doc.metadata.get("source", "unknown") results.append(f"[Source{i+1}: {source}]\n{doc.page_content[:300]}") return "\n\n---\n\n".join(results) # ========== Define RAG Agent Toolset ========== rag_agent_tools = [ Tool( name="Knowledge Base Search", func=search_knowledge_base, description="Search for information in the internal knowledge base. Use this tool when you need to find company documents, product information, or technical specifications. Input is a search keyword or question.", ), Tool( name="Python Execution", func=execute_python, # Reuse the previous function description="Execute Python code for data processing or calculations. Input is a Python code string.", ), ] # RAG Agent Specific Prompt RAG_AGENT_PROMPT = """You are a knowledge base Q&A Agent that can search the internal knowledge base and execute code. Available tools: {tools} Workflow: 1. For knowledge-based questions, prioritize using the "Knowledge Base Search" tool 2. For calculation needs, use the "Python Execution" tool 3. When answering, please cite the knowledge base source in the format [SourceX] 4. If the knowledge base does not have relevant information, please state so honestly Question: {input} Thought: {agent_scratchpad}""" prompt = PromptTemplate.from_template(RAG_AGENT_PROMPT) # Create RAG Agent rag_agent = create_react_agent(llm=llm, tools=rag_agent_tools, prompt=prompt) rag_executor = AgentExecutor( agent=rag_agent, tools=rag_agent_tools, verbose=True, handle_parsing_errors=True, max_iterations=6, ) # Test RAG Agent result = rag_executor.invoke({ "input": "What are the pricing standards for DeepSeek API? How much does it cost for 1 million tokens?", }) print(f"\nAnswer: {result['output']}")

RAG Agent Decision Flow

User Question Type Agent Decision Tool Used
"How to call the API?" Knowledge-based question, search knowledge base Knowledge Base Search
"Help me calculate the cost for 1 million tokens" First search prices, then calculate Knowledge Base Search + Python Execution
"Compare DeepSeek and GPT-4" Knowledge-based question, search information on both models Knowledge Base Search (multiple calls)

For more on building a RAG knowledge base, please see DeepSeek RAG Knowledge Base Building Tutorial.

Safety and Guardrails

Agents have tool-calling capabilities, which means they may execute dangerous operations. Safety guardrails are an essential component of Agent systems, ensuring that Agents operate within controlled boundaries.

Four Layers of Agent Safety

Protection Layer Purpose Implementation
Input Validation Filter malicious inputs to prevent injection attacks Regex filtering + content moderation API
Tool Permission Control Restrict the tools and parameter ranges an Agent can invoke Whitelist + parameter validation + rate limiting
Output Filtering Filter sensitive information to prevent data leakage Regex redaction + sensitive word filtering
Audit Logging Record all Agent operations for traceability Structured logs + database storage

Code Implementation of Safety Guardrails

import re import logging from functools import wraps from datetime import datetime # ========== 1. Input Validation ========== class InputGuard: """Input safety check""" # Dangerous patterns DANGEROUS_PATTERNS = [ r'rm\s+-rf', # delete command r'DROP\s+TABLE', # SQL injection r'__import__', # Python dangerous import r'os\.system', # system command r'eval\s*\(', # eval execution r'exec\s*\(', # exec execution ] MAX_INPUT_LENGTH = 10000 @classmethod def validate(cls, user_input: str) -> tuple[bool, str]: """Validate input, returns (is_safe, reason)""" if len(user_input) > cls.MAX_INPUT_LENGTH: return False, "Input length exceeds limit" for pattern in cls.DANGEROUS_PATTERNS: if re.search(pattern, user_input, re.IGNORECASE): return False, f"Dangerous pattern detected: {pattern}" return True, "OK" # ========== 2. Tool Permission Control ========== class ToolGuard: """Tool call safety control""" # Tool whitelist ALLOWED_TOOLS = {"search", "calculate", "get_weather"} # Call count limit per tool tool_call_count = {} MAX_CALLS_PER_TOOL = 10 MAX_TOTAL_CALLS = 30 @classmethod def check_tool_access(cls, tool_name: str, args: dict) -> tuple[bool, str]: """Check if tool call is allowed""" if tool_name not in cls.ALLOWED_TOOLS: return False, f"Tool '{tool_name}' is not in the whitelist" cls.tool_call_count[tool_name] = cls.tool_call_count.get(tool_name, 0) + 1 if cls.tool_call_count[tool_name] > cls.MAX_CALLS_PER_TOOL: return False, f"Tool '{tool_name}' call count exceeded" total = sum(cls.tool_call_count.values()) if total > cls.MAX_TOTAL_CALLS: return False, "Total call count exceeded" return True, "OK" # ========== 3. Output Filtering ========== class OutputGuard: """Output security filtering""" # Sensitive information patterns SENSITIVE_PATTERNS = [ (re.compile(r'\b\d{15,19}\b'), '[Bank card number hidden]'), (re.compile(r'\b1[3-9]\d{9}\b'), '[Phone number hidden]'), (re.compile(r'\b[\w.-]+@[\w.-]+\.\w+\b'), '[Email hidden]'), (re.compile(r'\b\d{6}(?:19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])\d{3}[\dXx]\b'), '[ID card number hidden]'), ] @classmethod def sanitize(cls, output: str) -> str: """Sanitize output content""" sanitized = output for pattern, replacement in cls.SENSITIVE_PATTERNS: sanitized = pattern.sub(replacement, sanitized) return sanitized # ========== 4. Audit Logging ========== logging.basicConfig( filename='agent_audit.log', level=logging.INFO, format='%(asctime)s | %(levelname)s | %(message)s', ) def log_agent_action(action: str, detail: dict): """Log Agent action""" logging.info(f"{action} | {json.dumps(detail, ensure_ascii=False)}") # ========== Safe Agent Wrapper ========== class SafeAgent: """Agent wrapper with safety guardrails""" def __init__(self, agent_executor): self.executor = agent_executor def run(self, user_input: str) -> str: # 1. Input validation safe, reason = InputGuard.validate(user_input) if not safe: log_agent_action("INPUT_REJECTED", {"reason": reason}) return f"Input rejected: {reason}" log_agent_action("INPUT_ACCEPTED", {"input": user_input[:100]}) # 2. Execute Agent try: result = self.executor.invoke({"input": user_input}) output = result["output"] except Exception as e: log_agent_action("EXECUTION_ERROR", {"error": str(e)}) return "Agent execution failed, please try again later." # 3. Output filtering safe_output = OutputGuard.sanitize(output) log_agent_action("OUTPUT_GENERATED", {"output": safe_output[:100]}) return safe_output

Security Best Practices

  • Never give the Agent direct access to the file system or database; use restricted APIs instead
  • Code execution tools must use a sandbox environment (Docker container or restricted Python)
  • All external API calls must go through a proxy, limiting rate and access scope
  • Regularly audit Agent logs to detect abnormal behavior promptly
  • Use System Prompt to clearly inform the Agent of security boundaries and prohibited behaviors

Production Deployment

Moving an Agent from development to production requires a comprehensive engineering approach. This chapter introduces how to build an Agent service using FastAPI, deploy with Docker containers, and set up monitoring and logging.

FastAPI Agent Service

# pip install fastapi uvicorn pydantic from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel, Field from typing import Optional import uvicorn import time app = FastAPI( title="DeepSeek Agent API", version="1.0.0", description="DeepSeek Agent intelligent agent service", ) # CORS configuration app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) # ========== Data Models ========== class AgentRequest(BaseModel): query: str = Field(..., min_length=1, max_length=5000) session_id: Optional[str] = None max_steps: int = Field(default=5, ge=1, le=20) class AgentResponse(BaseModel): success: bool answer: str steps: int tools_used: list[str] execution_time: float session_id: Optional[str] # ========== API Endpoints ========== @app.get("/health") async def health_check(): return {"status": "healthy", "model": "deepseek-chat"} @app.post("/agent/run", response_model=AgentResponse) async def run_agent(request: AgentRequest): """Execute Agent task""" start_time = time.time() tools_used = [] try: # Call your Agent executor here # result = safe_agent.run(request.query) # Example return answer = f"Agent has processed the query: {request.query}" return AgentResponse( success=True, answer=answer, steps=3, tools_used=tools_used, execution_time=round(time.time() - start_time, 3), session_id=request.session_id, ) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @app.post("/agent/chat") async def chat(request: AgentRequest): """Streaming chat endpoint (SSE)""" from fastapi.responses import StreamingResponse import asyncio async def generate(): # Simulate streaming output chunks = ["Analyzing the problem...", "Calling tools...", "Generating answer..."] for chunk in chunks: yield f"data: {chunk}\n\n" await asyncio.sleep(0.5) yield "data: [DONE]\n\n" return StreamingResponse(generate(), media_type="text/event-stream") # Start the service if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000, reload=True)

Docker Containerized Deployment

# Dockerfile FROM python:3.11-slim WORKDIR /app # Install dependencies COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # Copy application code COPY . . # Expose port EXPOSE 8000 # Start service CMD ["uvicorn", "agent_server:app", "--host", "0.0.0.0", "--port", "8000"] # requirements.txt # fastapi==0.115.0 # uvicorn[standard]==0.30.0 # openai==1.50.0 # langchain==0.3.0 # langchain-openai==0.2.0 # chromadb==0.5.0 # sentence-transformers==3.0.0 # pydantic==2.9.0 # docker-compose.yml # version: '3.8' # services: # agent: # build: . # ports: # - "8000:8000" # environment: # - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY} # volumes: # - ./chroma_db:/app/chroma_db # - ./agent_audit.log:/app/agent_audit.log # restart: unless-stopped # Build and start # docker-compose up -d --build

Monitoring and Logging

# pip install prometheus-client from prometheus_client import Counter, Histogram, Gauge, generate_latest from fastapi import Response # Define monitoring metrics agent_requests = Counter( 'agent_requests_total', 'Total Agent requests', ['status'], ) agent_duration = Histogram( 'agent_request_duration_seconds', 'Agent request duration', buckets=[0.5, 1, 2, 5, 10, 30], ) tool_calls = Counter( 'agent_tool_calls_total', 'Tool call count', ['tool_name'], ) active_sessions = Gauge( 'agent_active_sessions', 'Active sessions', ) # Expose Prometheus metrics endpoint @app.get("/metrics") async def metrics(): return Response(content=generate_latest(), media_type="text/plain")

Production Environment Checklist

Category Check Item Tool/Solution
Security Input validation, output filtering, tool permissions SafeAgent wrapper
Monitoring Request volume, latency, error rate, tool calls Prometheus + Grafana
Logging Request logs, tool call logs, error logs ELK / Loki / Structured logs
Rate Limiting API rate limiting, concurrency control slowapi / Redis + token bucket
Fault Tolerance Retry mechanism, degradation strategy, health checks tenacity + /health endpoint
Deployment Containerization, rolling updates, auto-scaling Docker + K8s + HPA

Deployment Recommendations

For small-scale applications, a single-machine Docker Compose deployment is sufficient. For production-grade applications, it is recommended to use a K8s cluster deployment with Prometheus + Grafana monitoring and ELK log collection. The Agent service is stateless and can be scaled horizontally, but attention must be paid to the concurrency limits of the LLM API.

DeepSeek Agent Development FAQ

ReAct mode or Function Calling: which should I choose? +
Function Calling is the recommended first choice. It uses structured JSON for parameter passing, avoiding the unreliability of regex parsing, and is natively supported by the DeepSeek API. ReAct mode is better for learning and understanding Agent principles, or for scenarios requiring highly customized output formats. In production, prioritize Function Calling.
What is the maximum number of tools an Agent can call? +
There is no hard limit in theory, but it is recommended to keep the number of tools between 5 and 10. Too many tools can make it difficult for the model to choose, increasing the error rate. If you really need more tools, you can group them by category and use a multi-Agent architecture, where each Agent is responsible for a set of related tools. DeepSeek API's Function Calling performs best with up to 10 tools.
What should I do if the Agent gets stuck halfway through execution? +
Setting the max_iterations or max_steps parameter is key to preventing infinite loops. Also, setting handle_parsing_errors=True in AgentExecutor can automatically handle format errors. If it gets stuck frequently, check: 1) Whether the Prompt is clear enough; 2) Whether the tool descriptions are accurate; 3) Whether a reasonable max_iterations (recommended 5-10) is set.
How to choose between multi-Agent and single Agent? +
Single Agent is suitable for clear, linear tasks (such as checking weather, calculating exchange rates). Multi-Agent is suitable for complex tasks that require division of labor and collaboration (such as research report writing, multi-step data analysis). The criterion: if a task can be completed by one person, use a single Agent; if teamwork is needed, use multi-Agent. CrewAI is the simplest multi-Agent framework for beginners.
Does the Agent consume a lot of tokens? How to optimize? +
Agent token consumption is indeed higher than normal conversation because each inference needs to carry the full conversation history and tool definitions. Optimization suggestions: 1) Use ConversationSummaryMemory to compress historical conversations; 2) Simplify tool descriptions and remove redundant information; 3) Set a reasonable max_iterations; 4) Use a sliding window to limit context length; 5) Consider using DeepSeek-V3's large context window to reduce compression overhead.
What is the difference between DeepSeek Agent and GPT-4 Agent? +
DeepSeek's Function Calling is fully compatible with the OpenAI format, making migration costs extremely low. On Agent tasks, DeepSeek-Chat performs excellently in reasoning and tool calling, and its price is much lower than GPT-4. DeepSeek-Reasoner has unique advantages in complex reasoning tasks. The main difference lies in the ecosystem: OpenAI's Assistant API provides a more complete managed Agent solution, while DeepSeek requires more self-building.

DeepSeek Related Tutorials

Learn more about using, deploying, and ecosystem tools for DeepSeek models.

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

完全免费,取消任意时间。我们不会发送垃圾邮件。