跪拜 Guibai
← Back to the summary

Three AI Agents That Cut a Dev Team's Weekly Grunt Work by 20 Hours

I Rebuilt My Daily Development Workflow with AI Agents, and the Results Were Surprising

After 5 years of coding, this is the first time I've felt AI is more than just "autocomplete"

Foreword

I don't know if you've felt this way—you've used a bunch of AI programming tools, but they always seem to fall short.

GitHub Copilot completes your code, but you still have to debug it yourself. Cursor lets you chat with AI, but you still have to make the changes yourself. ChatGPT writes functions for you, but you still have to assemble them yourself.

These tools feel more like "super autocomplete" than a "real developer."

That was until I started experimenting with AI Agents—turning your AI from a tool that only answers questions into a "digital colleague" that can plan, execute, and verify on its own.

This article documents the complete process of how I rebuilt my daily development workflow with AI Agents, from concept to implementation, from failure to success—all real-world experience.

What is an AI Agent? How is it different from regular AI tools?

Simply put:

For example, when I need to "add a logging system to the project":

How a regular AI tool handles it:

Me: Help me write a logging system
AI: Sure, here's the code... (returns a large block of code)
Me: Copy-paste → Modify → Debug → Find something missing → Ask again → Modify again

How an AI Agent handles it:

Me: Add a logging system to the project
Agent:
  1. Scan project structure, understand existing code style
  2. Create logger.ts file
  3. Modify main.ts to import logging
  4. Run lint check
  5. Find type errors, auto-fix them
  6. Run tests, confirm they pass
  7. Commit code with a commit message

See the difference? The Agent doesn't just "write code"—it "completes an entire development task."

My First Agent: Automated PR Review

In my team, every PR review was time-consuming. Reviewers had to check:

So I wrote a PR Review Agent based on GitHub Actions + Claude API.

Architecture Design

┌─────────────────────────────────────────────┐
│                  GitHub Webhook              │
│              (PR opened / updated)           │
└───────────────────┬─────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────────────┐
│              GitHub Actions                  │
│         (trigger review workflow)            │
└───────────────────┬─────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────────────┐
│              Review Agent                    │
│                                               │
│  1. Get PR diff                              │
│  2. Analyze code changes                     │
│  3. Check against project conventions        │
│  4. Generate review comments                 │
│  5. Auto-label issue severity                │
└───────────────────┬─────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────────────┐
│           GitHub PR Comment                  │
│     (auto-publish review results)            │
└─────────────────────────────────────────────┘

Core Code

// agent/review-agent.ts
import { Anthropic } from '@anthropic-ai/sdk';
import { context, getOctokit } from '@actions/github';

interface ReviewResult {
  file: string;
  line: number;
  severity: 'error' | 'warning' | 'suggestion';
  message: string;
  suggestion?: string;
}

class PRReviewAgent {
  private claude: Anthropic;
  private octokit: ReturnType<typeof getOctokit>;

  constructor(apiKey: string, githubToken: string) {
    this.claude = new Anthropic({ apiKey });
    this.octokit = getOctokit(githubToken);
  }

  async review(): Promise<ReviewResult[]> {
    // 1. Get PR changes
    const diff = await this.getPRDiff();
    const projectConfig = await this.getProjectConfig();

    // 2. Build prompt
    const prompt = this.buildPrompt(diff, projectConfig);

    // 3. Call AI for analysis
    const response = await this.claude.messages.create({
      model: 'claude-sonnet-4-20250514',
      max_tokens: 4096,
      messages: [{ role: 'user', content: prompt }],
      // Key: use tool_use to make AI return structured data
      tools: [{
        name: 'submit_review',
        description: 'Submit code review results',
        input_schema: {
          type: 'object',
          properties: {
            reviews: {
              type: 'array',
              items: {
                type: 'object',
                properties: {
                  file: { type: 'string' },
                  line: { type: 'number' },
                  severity: {
                    type: 'string',
                    enum: ['error', 'warning', 'suggestion']
                  },
                  message: { type: 'string' },
                  suggestion: { type: 'string' }
                },
                required: ['file', 'line', 'severity', 'message']
              }
            }
          },
          required: ['reviews']
        }
      }]
    });

    // 4. Parse results
    const reviews = this.parseToolResponse(response);
    return reviews;
  }

  private buildPrompt(diff: string, config: string): string {
    return `You are a senior frontend code reviewer. Please review the following PR changes.

## Project Conventions
${config}

## Review Points
1. TypeScript type safety: check for any type abuse, whether type assertions are reasonable
2. React performance: check for unnecessary re-renders, memo/useMemo usage
3. Code maintainability: function length, naming conventions, comment quality
4. Security risks: XSS risks, sensitive information leaks

## Code Changes
\`\`\`diff
${diff}
\`\`\`

Please provide specific modification suggestions, graded by severity.`;
  }
}

Actual Results

Data from the first month after deployment:

Metric Before After
Average PR Review Time 4.2 hours 1.1 hours
Code Convention Issue Miss Rate 23% 6%
Type Safety Issue Miss Rate 31% 4%
Reviewer Satisfaction - ⭐⭐⭐⭐⭐

What surprised me most was that the Agent caught several issues that reviewers had missed:

Second Agent: Automated API Documentation Generation

Our team has 200+ API endpoints, and the documentation could never keep up with code changes. Developers would say "I'll update the docs later," and then never did.

So I wrote an API Doc Agent that does something simple:

  1. Scans API route definitions in the code
  2. Extracts request parameters and return value types
  3. Derives field descriptions from TypeScript types
  4. Generates OpenAPI specification documentation
  5. Automatically updates the team's documentation platform

Key Implementation

// agent/api-doc-agent.ts
import * as ts from 'typescript';
import * as fs from 'fs';
import * as path from 'path';

interface APIEndpoint {
  path: string;
  method: string;
  handler: string;
  params: ParamInfo[];
  response: TypeInfo;
  description: string;
}

class APIDocAgent {
  private async scanRoutes(sourceDir: string): Promise<APIEndpoint[]> {
    const endpoints: APIEndpoint[] = [];

    // Traverse all .ts files
    const files = this.walkDir(sourceDir, '.ts');
    for (const file of files) {
      const source = fs.readFileSync(file, 'utf-8');
      const sourceFile = ts.createSourceFile(
        file, source, ts.ScriptTarget.Latest, true
      );

      // Traverse AST, find route definitions
      ts.forEachChild(sourceFile, (node) => {
        if (this.isRouteDefinition(node)) {
          const endpoint = this.extractEndpoint(node, sourceFile);
          if (endpoint) {
            endpoints.push(endpoint);
          }
        }
      });
    }

    return endpoints;
  }

  private async generateDescription(
    endpoint: APIEndpoint
  ): Promise<string> {
    // Use AI to generate description based on code context
    const prompt = `Please generate a Chinese description (within 50 characters) for the following API based on the code:

Path: ${endpoint.method} ${endpoint.path}
Handler: ${endpoint.handler}
Parameters: ${JSON.stringify(endpoint.params, null, 2)}
Return Value: ${JSON.stringify(endpoint.response, null, 2)}

Please describe: what this endpoint does, and in what scenario it is used.`;

    const response = await this.ai.complete(prompt);
    return response.trim();
  }

  private async generateOpenAPI(
    endpoints: APIEndpoint[]
  ): Promise<string> {
    const paths: Record<string, any> = {};

    for (const ep of endpoints) {
      const desc = await this.generateDescription(ep);

      if (!paths[ep.path]) {
        paths[ep.path] = {};
      }

      paths[ep.path][ep.method.toLowerCase()] = {
        summary: desc,
        operationId: ep.handler,
        parameters: ep.params.map(p => ({
          name: p.name,
          in: p.location,
          required: p.required,
          schema: { type: p.type }
        })),
        responses: {
          '200': {
            description: 'Success',
            content: {
              'application/json': {
                schema: ep.response
              }
            }
          }
        }
      };
    }

    return JSON.stringify({
      openapi: '3.0.0',
      info: { title: 'API Documentation', version: '1.0.0' },
      paths
    }, null, 2);
  }

  // Helper method: traverse directory
  private walkDir(dir: string, ext: string): string[] {
    const results: string[] = [];
    const list = fs.readdirSync(dir);
    for (const file of list) {
      const fullPath = path.join(dir, file);
      const stat = fs.statSync(fullPath);
      if (stat.isDirectory()) {
        results.push(...this.walkDir(fullPath, ext));
      } else if (fullPath.endsWith(ext)) {
        results.push(fullPath);
      }
    }
    return results;
  }
}

Actual Results

Previously, "API documentation updates" was a fixed complaint item in team weekly meetings. Now:

Third Agent: Automated Bug Fixing

This is the most aggressive and also the most practical of the three Agents.

Workflow

1. Get new bugs from Sentry
   ↓
2. Agent analyzes error stack trace, locates code
   ↓
3. Generate fix plan
   ↓
4. Create fix branch
   ↓
5. Apply fix
   ↓
6. Run tests
   ↓
7. Tests pass → Create PR
   Tests fail → Adjust fix plan (max 3 attempts)

Core Logic

// agent/bug-fix-agent.ts
class BugFixAgent {
  async fix(issue: SentryIssue): Promise<FixResult> {
    console.log(`🔍 Starting bug fix: ${issue.title}`);

    // 1. Analyze error
    const analysis = await this.analyzeError(issue);

    // 2. Generate fix
    let fix = await this.generateFix(analysis);
    let attempts = 0;

    // 3. Verify fix (max 3 retries)
    while (attempts < 3) {
      const branch = `fix/auto-${issue.id}-${Date.now()}`;
      await this.createBranch(branch);
      await this.applyFix(fix);

      const testResult = await this.runTests();
      if (testResult.passed) {
        // Tests passed, create PR
        await this.createPR(branch, issue.title, fix.description);
        return { success: true, branch, pr: fix.description };
      }

      // Tests failed, analyze failure reason and regenerate fix
      console.log(`❌ Fix attempt ${attempts + 1} failed, analyzing reason...`);
      fix = await this.retryFix(fix, testResult.failures);
      attempts++;
    }

    return { success: false, reason: 'All 3 fix attempts failed, manual intervention required' };
  }

  private async analyzeError(issue: SentryIssue): Promise<ErrorAnalysis> {
    const prompt = `You are a senior frontend engineer. Please analyze the following error:

## Error Information
${issue.title}
${issue.stackTrace}

## Related Code
${issue.sourceCode}

## Please Analyze
1. Root cause of the error
2. Scope of impact
3. Suggested fix plan
4. Risk assessment`;

    const response = await this.ai.complete(prompt);
    return this.parseAnalysis(response);
  }
}

Safety Boundaries

The biggest fear with letting AI auto-fix code is "fix one bug, introduce three new ones." I set up several hard rules:

  1. Only fix clearly reproducible errors: NullPointer, TypeError, uncaught Promises, etc.
  2. Prohibit modification of core business logic: Controlled via code path whitelist
  3. Must pass all tests: No merge unless tests pass
  4. Must have human review: PR requires at least one reviewer approval
  5. Gradual rollout: Fix non-critical bugs first → observe results → then open up more complex fixes

Overall Architecture of the Three Agents

I integrated the three Agents into a unified scheduling system:

┌──────────────────────────────────────────────────────┐
│                   Agent Scheduler                      │
│                                                        │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐ │
│  │ PR Review    │  │  API Doc     │  │  Bug Fix     │ │
│  │ Agent        │  │  Agent       │  │  Agent       │ │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘ │
│         │                 │                 │          │
│         └─────────┬───────┴─────────────────┘          │
│                   │                                    │
│                   ▼                                    │
│         ┌─────────────────┐                            │
│         │   Tool Registry │                            │
│         │                 │                            │
│         │  • file_system  │                            │
│         │  • git_ops      │                            │
│         │  • test_runner  │                            │
│         │  • github_api   │                            │
│         │  • sentry_api   │                            │
│         └─────────────────┘                            │
└──────────────────────────────────────────────────────┘

Each Agent shares the same tool registry but has different permission scopes:

Pitfalls and Lessons Learned

Pitfall 1: AI Overconfidence

Once, the Bug Fix Agent analyzed a Cannot read property 'map' of undefined error and confidently added a ?. optional chaining operator. Tests passed, and the PR was merged.

After deployment, we discovered the error was because the backend data structure had changed. Adding ?. only prevented the page from crashing, but no data was displayed at all—users saw a blank page.

Lesson: AI tends toward "minimal changes," but sometimes minimal changes only mask the problem rather than solving it. Now I've added a constraint in the prompt: "First analyze the root cause, then provide a fix plan."

Pitfall 2: Token Consumption Exceeded Expectations

When I first started, one month's Anthropic API bill shocked me—the PR Review Agent consumed about 20,000 tokens per review. With 15 PRs per day in the team, that's 9 million tokens a month.

Lesson: Optimize prompts, only pass changed diffs, not entire files. Use lighter models for pre-screening (e.g., first use a small model to determine if there's an issue, then hand off to a large model for detailed analysis only if there is).

Pitfall 3: Agent "Hallucinations"

Once, the API Doc Agent generated this description for a user deletion endpoint: "This endpoint is used to delete users. Please ensure the user has logged out before calling." But the actual code had no logic for "ensure the user has logged out"—the AI made that up.

Lesson: AI-generated content must be annotated with its source, so reviewers can quickly determine what was inferred from code and what was guessed by AI.

Summary: AI Agents Are Not a Silver Bullet

After months of practice, my biggest takeaway is: AI Agents are not here to replace developers, but to amplify developers.

What they're good at:

What they're not good at:

So my strategy is: Let Agents do 80% of the grunt work, while I focus on the 20% of decision-making work.

This Agent system is open-sourced on GitHub (see end of article). The three Agents combined are less than 2,000 lines of code, but they save our team about 20 hours of work time per week.

If you're also considering using AI Agents to transform your development process, my advice is: Start from a minimal viable scenario, close the loop, then gradually expand. Don't try to build a "fully automated development Agent" right from the start—that will likely exhaust both your patience and your budget.


Reference Resources


Extension: Agent Prompt Engineering in Practice

Many people think Agents are just about "throwing tasks at AI," but in reality, the quality of prompts directly determines Agent performance. Here are a few pitfalls I've encountered and techniques I've summarized.

Technique 1: Give Agents Clear Task Boundaries

When I first wrote the PR Review Agent, the prompt was just one sentence: "Please review this PR." As a result, the AI would give all sorts of absurd suggestions—like recommending a rewrite of the entire architecture or introducing new design patterns, completely deviating from the purpose of Code Review.

Later, I changed the prompt to:

You are a code reviewer. Your review scope is limited to:
1. Whether code style conforms to ESLint configuration
2. Whether TypeScript types are safe
3. Whether there are obvious performance issues (e.g., unnecessary calculations in loops)
4. Whether there are security risks (XSS, sensitive information leaks)

Prohibited from reviewing:
- Architecture design (handled by architects)
- Business logic correctness (ensured by testing)
- Naming style preferences (determined by team conventions)

The effect was immediate—review content went from "all over the place" to "precise strikes."

Technique 2: Use Few-Shot Examples to Guide Output Format

When I first started the Bug Fix Agent, the AI's fix code style was very inconsistent—sometimes using if (!data) return null, sometimes data?.map(), sometimes try-catch. The lack of consistency made it hard for reviewers to build trust.

My solution: provide 3 examples in the prompt, letting the AI mimic the team's existing fix patterns.

const FEW_SHOT_EXAMPLES = `
## Fix Examples

### Example 1: NullPointer Fix
**Error Code**:
const name = user.profile.name; // TypeError: Cannot read property 'name'

**Fix Plan**:
const name = user?.profile?.name ?? 'Unknown User';

### Example 2: Async Error Handling
**Error Code**:
const data = await fetchUser(id);

**Fix Plan**:
try {
  const data = await fetchUser(id);
} catch (error) {
  logger.error('Failed to fetch user', { id, error });
  throw new UserFetchError(id, error);
}

### Example 3: Memory Leak Fix
**Error Code**:
useEffect(() => {
  const timer = setInterval(() => updateTime(), 1000);
}, []);

**Fix Plan**:
useEffect(() => {
  const timer = setInterval(() => updateTime(), 1000);
  return () => clearInterval(timer);
}, []);
`;

With these examples, the AI's fix code style became almost identical to the team's hand-written code.

Technique 3: Add a "Self-Questioning" Step

This is a technique I learned from a paper. Add this at the end of the prompt:

Before outputting the final plan, please self-question:
1. Does this fix introduce new problems?
2. Is there a simpler solution?
3. Have edge cases been considered (null values, concurrency, timeouts)?

This small change increased the Bug Fix Agent's first-attempt fix success rate from 62% to 78%.

Cost Analysis: Is It Worth It?

Many people are concerned about costs. Let me share the data directly.

Monthly Cost Breakdown

Agent Call Frequency Tokens per Call Monthly Consumption Cost (approx.)
PR Review Agent 15 times/day 8000 tokens 3.6M tokens ¥180
API Doc Agent Trigger-based 20000 tokens 600K tokens ¥30
Bug Fix Agent 3 times/day 15000 tokens 1.35M tokens ¥68
Total - - 5.55M tokens ¥278

Comparison with Human Labor Cost

Scenario Human Time Agent Time Savings
PR Review 30 min/time 3 min/time 33 hours/week
API Doc Update 2 hours/time 5 min/time On-demand
Bug Fix 1 hour/time 10 min/time 5 hours/week

Monthly ROI: Invest ¥278, save approximately 152 hours of human labor ≈ save ¥30,000+

So you ask me if it's worth it? Spending less than 300 yuan to get a "tireless junior developer"—this deal is a steal.

Final Thoughts

The essence of AI Agent development is not "letting AI replace people," but "letting AI become the hardest-working junior developer on the team"—it doesn't complain, doesn't take leave, doesn't slack off, and is on standby 24/7.

And you, as the "senior developer," need to:

  1. Clearly define what it should do (task boundaries)
  2. Tell it how to do it right (examples and conventions)
  3. Check whether it did it right (verification and review)

This is exactly the daily routine of a senior developer mentoring a junior developer, except your "apprentice" is AI.

This article is the first in the "AI Programming" series. In the next one, I'll dive deep into how to use the MCP protocol to connect your Agent to more tools, such as databases, Feishu, Jira, etc.