Skip to main content

Hands-On Session #2: Building Custom Agents & Rules

Build Custom Agents or customize existing agent behavior with the 3 building blocks of agentic workflows: Context, Tools, Triggers.

In this session, you'll learn how to customize agentic behavior by creating both Rules (which enhance the context provided to your agents) and Agents (which replace or extend default behavior from system instructions, enabling you to test and refine your own agentic behavior).

Understanding Rules vs Agents

Before we dive in, let's understand the key difference:

RulesAgents
EffectAdditive; enhances existing behavior by providing additional contextReplacement; overrides (or extends) system instructions for full control of agentic behavior
Use whenYou want to add context or customize behaviorYou want full control from scratch
Risk levelLow; Agents still have their base capabilitiesHigher; you're responsible for a large part of the agentic harness

Part 1: Create a Rule

What are Rules?

Rules are conditional instructions that get injected into Otto's context. They enhance Otto's behavior without replacing it.

Rules can be configured to only apply in specific situations using:

  • globs: Match specific file patterns (e.g., *.py, *.sql)
  • keywords: Match when certain words appear in the conversation

Step 1: Create a code style guide rule

Let's create a rule that applies when working with code files, ensuring consistent code quality across your project.

You can ask Otto to create this file for you by asking:

Create a new rule that applies when working with code files, ensuring consistent code quality across the project.

Or you can create the file manually:

  1. Right-click on the otto/rules/ folder
  2. Select New file
  3. Name the file code-style-guide.md
  4. Paste the following content:
---
otto:
rule:
alwaysApply: true
description: "Code style guide for data engineering"
globs: ["*.py", "*.sql"]
keywords: []
---

# Code Style Guide

When writing or reviewing code, follow these standards:

## Python Style

### Naming Conventions
- Use `snake_case` for functions and variables
- Use `PascalCase` for classes
- Use `UPPER_CASE` for constants
- Use descriptive names that explain intent (e.g., `calculate_discount` not `calc`)

### Code Structure
- Keep functions focused on a single responsibility
- Limit function length to 50 lines or less
- Use type hints for function parameters and return values
- Add docstrings to all functions and classes

### Best Practices
- Avoid magic numbers — use named constants
- Handle errors explicitly — never use bare `except:` clauses
- Use list comprehensions for simple transformations
- Prefer `is` and `is not` over `==` and `!=` for None comparisons

### Formatting
- Use 4 spaces for indentation (no tabs)
- Maximum line length: 100 characters
- Add blank lines between functions and classes
- Use trailing commas in multi-line structures

## SQL Style

### Naming Conventions
- Use `snake_case` for table and column names
- Use descriptive aliases (e.g., `customer_id AS cust_id` not `c AS id`)
- Prefix temporary tables with `tmp_` or `temp_`

### Query Structure
- Use CTEs for complex queries instead of nested subqueries
- Avoid `SELECT *` — explicitly list columns
- Use `WHERE` clauses to filter early in the query
- Add comments for complex business logic

### Performance
- Use appropriate indexes
- Avoid functions in WHERE clauses when possible
- Use `EXISTS` instead of `IN` for subqueries when checking existence
- Consider partitioning for large tables

## General Principles

- **Readability over cleverness**: Code should be easy to understand
- **DRY (Don't Repeat Yourself)**: Extract common patterns into functions
- **Document why, not what**: Comments should explain reasoning, not restate code
  1. Save the file with Cmd+S or Ctrl+S

Step 2: Test your rule

  1. Open Otto chat (Ctrl+I)
  2. Ask Otto to write new code:
Create sql transform on the sales component by adding: sale_date/hour/day_of_week from timestamp, channel logic (Store/Vendor/Website based on store_id/vendor_id), and calculated totals (price * quantity, with tax)

Notice how Otto now references your style guide when working with code files! You can see all the rules Otto has applied by hovering over the icon above your last prompt.


[Optional] Part 2: Create a Code Reviewer Agent

What are Agents?

Agents replace or extend Otto's default system instructions entirely. For this track, we'll create an agent that systematically reviews code and provides structured, actionable feedback.

warning

Creating a custom agent overrides Otto's system instructions unless you add extends: otto. Your agent won't have Otto's built-in behaviors unless you explicitly include them. This is an excellent opportunity to practice context engineering from scratch! See the Custom Agents reference for more details.

Step 1: Create the agent

Ask Otto to create the agent for you by asking:

Please create a new agent that reviews code and provides structured, actionable feedback.

Or you can create the file manually:

  1. Right-click on the otto/agents/ folder
  2. Select New file
  3. Name the file code_reviewer.md
  4. Paste the following content:
---
otto:
agent:
name: code_reviewer
extends: otto
# tools: ["*"] # optionally restrict to a subset of tools
---

# Code Reviewer Agent

You are an expert code reviewer specializing in data engineering code. Your job is to systematically analyze code and provide comprehensive, structured reviews.

## Your Review Process

When reviewing code, you must follow this exact workflow:

1. **Read and analyze** the code thoroughly
- Understand what the code is trying to accomplish
- Identify all files and functions being reviewed
- Note the context and dependencies

2. **Check against style guide**
- Reference any code style rules that apply
- Verify naming conventions are followed
- Check formatting and structure

3. **Identify issues systematically**
- Style violations (naming, formatting, structure)
- Best practice violations (error handling, efficiency, maintainability)
- Potential bugs (logic errors, edge cases, type issues)
- Performance concerns (inefficient queries, unnecessary operations)
- Security issues (SQL injection risks, sensitive data exposure)

4. **Prioritize findings**
- **Critical**: Bugs that will cause failures or data corruption
- **High**: Performance issues or security concerns
- **Medium**: Style violations that impact readability
- **Low**: Minor improvements or suggestions

5. **Provide actionable feedback**
- For each issue, explain what's wrong and why
- Provide specific line numbers or code locations
- Suggest concrete fixes with code examples

## Required Output Format

Your review MUST follow this exact structure:

### 📊 Review Summary

- **Files reviewed**: [list of files]
- **Total issues found**: [number]
- Critical: [count]
- High: [count]
- Medium: [count]
- Low: [count]
- **Overall assessment**: [1-2 sentence summary]

### 🔴 Critical Issues

For each critical issue:
- **Issue**: [brief description]
- **Location**: [file:line or function name]
- **Impact**: [what could go wrong]
- **Fix**: [specific solution with code example]

### ⚠️ High Priority Issues

[Same format as Critical Issues]

### 📝 Medium Priority Issues

[Same format as Critical Issues]

### 💡 Low Priority / Suggestions

[Same format as Critical Issues]

### ✅ Positive Observations

- [What the code does well]

### 🔧 Recommended Next Steps

1. [Action item 1]
2. [Action item 2]
3. [Action item 3]

## Review Guidelines

- Be thorough but constructive — focus on helping improve the code
- Provide code examples for all suggested fixes
- Explain the "why" behind each recommendation
- Prioritize issues that could cause production problems
- Acknowledge good practices when you see them
- If reviewing multiple files, organize findings by file

Remember: Your goal is to help write better, more maintainable code.
  1. Save the file with Cmd+S or Ctrl+S

Step 2: Test your agent

  1. Open Otto chat (Ctrl+I)
  2. Click on Otto at the bottom of the chat panel
  3. Select your Code Reviewer agent
Select custom agent
  1. Paste this code for review:
Review this Python code and suggest improvements:

```python
# calculate the discount for custoemrs
def calc(t,x,h,z):
data = []
if t=="gold":
d=0.2
elif t=="silver":
d=0.1
elif t=="bronze":
d=0.05
elif t=="platinum":
d=0.25
else:
d=0
if h==True:
d=d+0.05
if z==True:
if t=="gold" or t=="platinum":
d=d+0.1
else:
d=d+0.02
f=x*(1-d)
# TODO: fix this later
try:
result = f / x * 100
except:
pass
return f
```
  1. Notice how the agent provides a structured review with prioritized issues and specific fixes!
Before continuing

Switch back to the default Otto agent before proceeding with the lab. Click on your agent name at the bottom of the chat panel and select Otto to restore the default behavior.


[Optional] Part 3: Automate Weekly Code Reviews

Now that you have a code style guide rule and a code reviewer agent, let's create an automation that runs weekly to review all code changes and send you a comprehensive report.

What are Automations?

Automations in Ascend enable automatic triggering of actions based on defined conditions. They combine triggers (sensors for time-based schedules or events for system events) with actions (like running Otto) to create intelligent workflows.

Step 1: Create the automation

Create the Automation file:

  1. Right-click on the automations/ folder
  2. Select New file
  3. Name the file weekly-code-review.yaml
  4. Paste the following content:
automation:
name: weekly-code-review
enabled: true
triggers:
sensors:
- type: timer
name: weekly-timer
config:
schedule:
cron: '0 9 * * MON' # Every Monday at 9 AM UTC
actions:
- type: run_otto
name: weekly-code-review
config:
agent_name: code_reviewer
prompt: >-
# Weekly Code Review Instructions

You are being invoked as part of a weekly automated code review process.
Your job is to analyze all code changes made in the past week and provide
a comprehensive review. You cannot ask for help or clarification; you must
complete this end-to-end based on your own analysis.

## Your Tasks

1. **Identify all code changes from the past week**
- Review git history to find all commits from the last 7 days
- Identify which files were modified, added, or deleted
- Focus on Python (.py) and SQL files

2. **Review each changed file**
- Apply the code style guide rules
- Check for best practices violations
- Identify potential bugs or performance issues
- Look for security concerns

3. **Compile a comprehensive report**
- Follow your standard review output format
- Organize findings by file
- Prioritize issues by severity
- Include positive observations where code quality is good

4. **Flag items needing attention**
- Highlight any critical issues that require immediate action
- Note any patterns of recurring issues across files
- Suggest areas for improvement in the codebase

## Report Structure

Your report should include:

### Week Summary
- Date range covered
- Total files changed
- Total lines added/removed
- Overall code quality assessment

### Files Reviewed
[List each file with a brief summary]

### Critical Issues Requiring Attention
[Issues that must be addressed]

### Code Quality Trends
[Patterns you notice across the week's changes]

### Recommendations
[Actionable next steps]

Be thorough, constructive, and focus on helping maintain high code quality
standards across the project. You cannot ask the user for help. You must send the user an email.
  1. Save the file with Cmd+S or Ctrl+S

Step 2: Test your automation

Before deploying, let's test the automation manually:

  1. Open Otto chat (Ctrl+I)
  2. Make sure you're using the default Otto agent (not the Code Reviewer)
  3. Ask Otto to execute the automation's prompt:
Please follow the exact instructions in the weekly-code-review automation and generate a weekly code review based on my Workspace activity from the past week. Provide the comprehensive report as specified.

This will show you what the automated review will look like when it runs!

Checkpoint

By the end of this session, you should have:

  • Explored the otto/ directory structure
  • Created a custom Rule
  • Created a custom Agent
  • Tested both customizations
  • Understood the difference between Rules (additive) and Agents (replacement)
  • Created an Automation to run your agent on a schedule (you'll deploy this later!)
Need help?

Ask a bootcamp instructor or reach out in the Ascend Community Slack.

Next steps

Continue to the Agentic Data Operations Labs to build an end-to-end data pipeline!