This guide demonstrates how to build an intelligent code agent that can analyze and manipulate codebases using Codegen’s LangChain integration.

This agent access to powerful code viewing and manipulation tools powered by Codegen, including:

  • RevealSymbolTool: reveal all N-th degree dependencies and usages of a function
  • MoveSymbolTool: move a symbol between files, updating all imports etc. (guaranteed correctness)
  • SemanticEditTool: implementation of Cursor-style smart file editing
  • SemanticSearchTool: search over an index of vector embeddings for files
View the full code in our examples repository

Step 1: Setting Up the Agent

First, let’s import the necessary components and create our agent:

from langchain_openai import ChatOpenAI
from codegen import Codebase
from codegen.extensions.langchain import create_codebase_agent

# Initialize codebase
codebase = Codebase.from_repo("fastapi/fastapi")

# Create the agent with GPT-4
agent = create_codebase_agent(
    codebase=codebase,
    model_name="gpt-4",
    temperature=0,
    verbose=True
)

The agent is initialized with:

  • A Codebase instance to operate on
  • An LLM (GPT-4 in this case)
  • Tools for code manipulation
  • A conversation memory to maintain context

Step 2: Available Tools

The agent comes with several built-in tools for code operations:

tools = [
    ViewFileTool(codebase),      # View file contents
    ListDirectoryTool(codebase),  # List directory contents
    SearchTool(codebase),        # Search code
    EditFileTool(codebase),      # Edit files
    CreateFileTool(codebase),    # Create new files
    DeleteFileTool(codebase),    # Delete files
    RenameFileTool(codebase),    # Rename files
    MoveSymbolTool(codebase),    # Move functions/classes
    RevealSymbolTool(codebase),  # Analyze symbol relationships
    SemanticEditTool(codebase),  # Make semantic edits
    CommitTool(codebase),        # Commit changes
]

Each tool provides specific capabilities to the agent, allowing it to perform complex code operations.

Step 3: Interacting with the Agent

Let’s see some examples of how to interact with the agent:

# Analyze dependencies
result = agent.invoke(
    {
        "input": "What are the dependencies of the FastAPI class?",
        "config": {"configurable": {"session_id": "demo"}}
    }
)
print(result["output"])

# Find usage patterns
result = agent.invoke(
    {
        "input": "Show me examples of dependency injection in the codebase",
        "config": {"configurable": {"session_id": "demo"}}
    }
)
print(result["output"])

# Perform code analysis
result = agent.invoke(
    {
        "input": "What's the most complex function in terms of dependencies?",
        "config": {"configurable": {"session_id": "demo"}}
    }
)
print(result["output"])

The agent maintains conversation history, so it can reference previous queries and build context over time.

Step 4: Code Manipulation

The agent can also perform code changes:

# Move a function to a new file
result = agent.invoke(
    {
        "input": "Move the validate_email function to validation_utils.py",
        "config": {"configurable": {"session_id": "demo"}}
    }
)

# Rename a class and update all references
result = agent.invoke(
    {
        "input": "Rename the UserModel class to User and update all imports",
        "config": {"configurable": {"session_id": "demo"}}
    }
)

# Add error handling
result = agent.invoke(
    {
        "input": "Add proper error handling to the process_data function",
        "config": {"configurable": {"session_id": "demo"}}
    }
)

The agent will:

  1. Analyze the current code state
  2. Plan the necessary changes
  3. Execute the changes while maintaining code correctness
  4. Update all related imports and references

Advanced Usage

Adding Custom Tools

You can extend the agent with custom tools:

from langchain.tools import BaseTool
from pydantic import BaseModel, Field

class CustomToolInput(BaseModel):
    """Input schema for custom tool."""
    param: str = Field(..., description="Parameter description")

class CustomCodeTool(BaseTool):
    """A custom tool for the code agent."""
    name = "custom_tool"
    description = "Description of what the tool does"
    args_schema = CustomToolInput

    def _run(self, param: str) -> str:
        # Tool implementation
        return f"Processed {param}"

# Add custom tool to agent
tools.append(CustomCodeTool())
agent = create_codebase_agent(
    codebase=codebase,
    tools=tools,
    model_name="gpt-4"
)