Skip to content

Commit 71eda03

Browse files
committed
feat(examples): add Hy3-powered code review agent (#92)
- Automated code review agent using trpc-agent-sdk + Hy3 LLM - Structured review with bug/security/improvement detection - SQLite persistence for review results - OpenAI-compatible model config (works with Hy3 API) Fixes #92 Assisted-by: claude-code:deepseek-v4-pro
1 parent e113610 commit 71eda03

7 files changed

Lines changed: 174 additions & 0 deletions

File tree

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Code Review Agent
2+
3+
An automated AI code reviewer built with tRPC-Agent SDK, backed by Hy3 LLM.
4+
5+
## Features
6+
7+
- **Structured review**: Bugs, style, security, improvement suggestions
8+
- **SQLite persistence**: All reviews saved to `code_reviews.db`
9+
- **Skills-ready**: Can be extended with CubeSandbox skills for sandboxed execution
10+
11+
## Quick Start
12+
13+
```bash
14+
pip install -e '.[cube]' # from trpc-agent-python root
15+
16+
export TRPC_AGENT_API_KEY=your-hy3-key
17+
export TRPC_AGENT_BASE_URL=http://127.0.0.1:8000/v1
18+
export TRPC_AGENT_MODEL_NAME=tencent/Hy3
19+
20+
python run_agent.py path/to/your/code.py
21+
```
22+
23+
## Architecture
24+
25+
```
26+
User → Code Review Agent (Hy3 LLM)
27+
├── review_code() → Analyze code
28+
├── save_review() → SQLite persistence
29+
└── skills (optional) → CubeSandbox sandbox
30+
```

examples/code_review_agent/agent/__init__.py

Whitespace-only changes.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from trpc_agent_sdk.agents import LlmAgent
2+
from trpc_agent_sdk.models import LLMModel, OpenAIModel
3+
from trpc_agent_sdk.tools import FunctionTool
4+
5+
from .config import get_model_config
6+
from .prompts import INSTRUCTION
7+
from .tools import review_code, save_review
8+
9+
10+
def _create_model() -> LLMModel:
11+
api_key, url, model_name = get_model_config()
12+
return OpenAIModel(model_name=model_name, api_key=api_key, base_url=url)
13+
14+
15+
def create_agent() -> LlmAgent:
16+
return LlmAgent(
17+
name="code_reviewer",
18+
description="An AI-powered code review agent backed by Hy3.",
19+
model=_create_model(),
20+
instruction=INSTRUCTION,
21+
tools=[
22+
FunctionTool(review_code),
23+
FunctionTool(save_review),
24+
],
25+
)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import os
2+
3+
4+
def get_model_config():
5+
api_key = os.environ.get("TRPC_AGENT_API_KEY", "EMPTY")
6+
url = os.environ.get("TRPC_AGENT_BASE_URL", "http://127.0.0.1:8000/v1")
7+
model_name = os.environ.get("TRPC_AGENT_MODEL_NAME", "tencent/Hy3")
8+
return api_key, url, model_name
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
INSTRUCTION = """You are an expert code reviewer. When a user provides code:
2+
3+
1. Use `review_code` to analyze the code and produce a structured review.
4+
2. Use `save_review` to persist the review results to the database.
5+
3. Summarize the most important findings for the user.
6+
7+
Always reference specific line numbers in your findings. Be constructive, not critical."""
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
"""Code review tools: review code, save results to database."""
2+
import sqlite3
3+
import json
4+
from datetime import datetime
5+
6+
DB_PATH = "code_reviews.db"
7+
8+
9+
def _get_db():
10+
conn = sqlite3.connect(DB_PATH)
11+
conn.execute("""
12+
CREATE TABLE IF NOT EXISTS reviews (
13+
id INTEGER PRIMARY KEY AUTOINCREMENT,
14+
file_path TEXT,
15+
summary TEXT,
16+
bugs TEXT,
17+
improvements TEXT,
18+
score INTEGER,
19+
created_at TEXT
20+
)
21+
""")
22+
return conn
23+
24+
25+
def review_code(code: str, file_path: str = "") -> dict:
26+
"""Analyze code and return structured review.
27+
28+
This is a tool the agent calls — the actual LLM analysis happens
29+
through the agent's model. The returned dict is the structured
30+
output template.
31+
"""
32+
return {
33+
"code_snippet": code[:500],
34+
"file_path": file_path,
35+
"needs_review": True,
36+
}
37+
38+
39+
def save_review(file_path: str, summary: str, bugs: str,
40+
improvements: str, score: int = 0) -> str:
41+
"""Save a code review to the SQLite database.
42+
43+
Args:
44+
file_path: Path to the reviewed file
45+
summary: One-sentence summary
46+
bugs: Bug findings
47+
improvements: Suggested improvements
48+
score: Quality score (0-10)
49+
"""
50+
conn = _get_db()
51+
conn.execute(
52+
"INSERT INTO reviews (file_path, summary, bugs, improvements, score, created_at) "
53+
"VALUES (?, ?, ?, ?, ?, ?)",
54+
(file_path, summary, bugs, improvements, score, datetime.now().isoformat())
55+
)
56+
conn.commit()
57+
count = conn.execute("SELECT COUNT(*) FROM reviews").fetchone()[0]
58+
conn.close()
59+
return f"Review saved. Total reviews in database: {count}"
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""Run the code review agent.
2+
3+
Usage::
4+
5+
export TRPC_AGENT_API_KEY=your-hy3-key
6+
export TRPC_AGENT_BASE_URL=http://127.0.0.1:8000/v1
7+
python run_agent.py path/to/file.py
8+
"""
9+
10+
import asyncio
11+
import sys
12+
13+
from trpc_agent_sdk.runners import Runner
14+
from trpc_agent_sdk.sessions import InMemorySessionService
15+
16+
from agent.agent import create_agent
17+
18+
19+
async def main():
20+
if len(sys.argv) < 2:
21+
print("Usage: python run_agent.py <filepath>")
22+
sys.exit(1)
23+
24+
filepath = sys.argv[1]
25+
with open(filepath, "r", encoding="utf-8") as f:
26+
code = f.read()
27+
28+
agent = create_agent()
29+
session_service = InMemorySessionService()
30+
31+
prompt = (
32+
f"Please review the following code file ({filepath}).\n"
33+
f"Call review_code first, then save_review with a score from 0-10, "
34+
f"and summarize your findings:\n\n```\n{code[:20000]}\n```"
35+
)
36+
37+
runner = Runner(agent=agent, session_service=session_service)
38+
async for event in runner.run(prompt):
39+
if event.content:
40+
print(event.content, end="", flush=True)
41+
print()
42+
43+
44+
if __name__ == "__main__":
45+
asyncio.run(main())

0 commit comments

Comments
 (0)