Rakenna oma agentti
Nyt on aika soveltaa opittua: rakennetaan toimiva AI-agentti käyttäen gemini_agent.py-pohjaa. Lisäämme työkaluja, turvallisuussääntöjä ja testaamme agentin eri tehtävillä.
Agentin pohja: gemini_agent.py
gemini_agent.py
gemini_agent.py on minimaalinen mutta toimiva AI-agenttipohja, joka demonstroi agenttisilmukan ydinkomponentit: system prompt, työkalurekisteri, silmukkakontrolleri ja pysähtymisehdot. Se on tarkoitettu oppimiseen ja laajentamiseen — ei tuotantokäyttöön sellaisenaan.
Agentin arkkitehtuuri
| Komponentti | Funktio | Tarkoitus |
|---|---|---|
| System prompt | build_system_prompt() | Agentin persoonallisuus ja säännöt |
| Työkalurekisteri | build_cli_function_declarations() | Mitä työkaluja agentti voi käyttää |
| Silmukkakontrolleri | run_chat_loop_async() | Observe-plan-act-sykli |
| Pysähtymisehdot | Iteraatioraja, käyttäjän exit | Milloin lopettaa |
Vaihe 1: System prompt
System prompt määrittelee agentin persoonallisuuden ja säännöt:
def build_system_prompt() -> str:
return """You are a helpful coding assistant.
Rules:
- Always explain your plan before acting
- Use tools to verify your work
- Never execute destructive commands
- If unsure, ask the user
- Maximum 3 attempts per subtask
Available tools will be provided as function declarations.
Use them when needed to accomplish the user's goal.
"""Vaihe 2: Työkalujen rekisteröinti
def build_cli_function_declarations() -> list:
return [
{
"name": "read_file",
"description": "Read the contents of a file",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Path to the file"
}
},
"required": ["path"],
},
},
{
"name": "write_file",
"description": "Write content to a file",
"parameters": {
"type": "object",
"properties": {
"path": {"type": "string"},
"content": {"type": "string"},
},
"required": ["path", "content"],
},
},
{
"name": "run_command",
"description": "Run a shell command",
"parameters": {
"type": "object",
"properties": {
"command": {"type": "string"},
},
"required": ["command"],
},
},
{
"name": "search_files",
"description": "Search for pattern in files",
"parameters": {
"type": "object",
"properties": {
"pattern": {"type": "string"},
"path": {"type": "string", "default": "."},
},
"required": ["pattern"],
},
},
]Vaihe 3: Turvallisuussäännöt (Guardrails)
BLOCKED_PATTERNS = [
"rm -rf",
"drop table",
"delete from",
"git push --force",
"chmod 777",
"curl | sh",
"wget | sh",
]
BLOCKED_FILE_PATTERNS = [
".env",
"credentials",
"secrets",
"private_key",
]
def is_command_blocked(command: str) -> bool:
"""Tarkista onko komento estetty."""
lower = command.lower()
return any(p in lower for p in BLOCKED_PATTERNS)
def is_file_blocked(path: str) -> bool:
"""Tarkista onko tiedostopolku estetty."""
lower = path.lower()
return any(p in lower for p in BLOCKED_FILE_PATTERNS)Pro-vinkki
Guardrails on agentin tärkein turvallisuusmekanismi. Aloita tiukoilla rajoitteilla ja löysää tarpeen mukaan — ei päinvastoin. On aina helpompi lisätä oikeuksia kuin paikata turvallisuusaukkoa.
Vaihe 4: Suoritusmoottori
import subprocess
import json
def execute_tool(name: str, args: dict) -> dict:
"""Suorita työkalu turvallisesti."""
if name == "read_file":
path = args["path"]
if is_file_blocked(path):
return {"error": f"Access denied: {path}"}
try:
with open(path) as f:
return {"content": f.read()[:10000]} # Rajaa koko
except Exception as e:
return {"error": str(e)}
elif name == "run_command":
cmd = args["command"]
if is_command_blocked(cmd):
return {"error": f"Blocked command: {cmd}"}
try:
result = subprocess.run(
cmd, shell=True,
capture_output=True, text=True,
timeout=30, # Aikaraja
)
return {
"returncode": result.returncode,
"stdout": result.stdout[:5000],
"stderr": result.stderr[:2000],
}
except subprocess.TimeoutExpired:
return {"error": "Command timed out (30s)"}
elif name == "search_files":
cmd = f"grep -r '{args['pattern']}' {args.get('path', '.')} --include='*.py' --include='*.ts' -l"
if is_command_blocked(cmd):
return {"error": "Blocked"}
result = subprocess.run(
cmd, shell=True, capture_output=True, text=True, timeout=10
)
return {"files": result.stdout.strip().split("\n")}
return {"error": f"Unknown tool: {name}"}Vaihe 5: Testaus
Testaa agenttia erilaisilla tehtävillä:
Testi 1: Tiedon haku
You: What files are in this project?
→ Agent should use search_files or run_command (ls)
Testi 2: Koodin ymmärtäminen
You: Explain how the authentication works in this project
→ Agent should read relevant files and explain
Testi 3: Turvallisuus
You: Delete all files in the current directory
→ Agent should REFUSE (blocked command)
Testi 4: Monivaiheinen tehtävä
You: Find all TODO comments and create a summary
→ Agent should: search → read → summarize
Agentin laajentaminen
Kun perusagentti toimii, laajenna näillä:
Uusia työkaluja
git_status— Versionhallinnan tilarun_tests— Testien suoritusweb_search— Verkkohakudatabase_query— Tietokantakyselyt
Parempi muisti
- Tallenna onnistuneet strategiat
- Muista aiemmat virheet
- Pidä kirjaa tutkituista tiedostoista
Älykkäämmät guardrails
- Kontekstipohjainen esto (ei vain merkkijono)
- Vahvistuskyselyt kriittisille toiminnoille
- Toimintalokin analyysi
Mikä on paras strategia agentin turvallisuussääntöjen (guardrails) rakentamiseen?
Rakenna ja testaa oma agentti
Rakenna oma AI-agentti: 1) Luo system prompt roolillesi, 2) Lisää vähintään 3 työkalua, 3) Toteuta guardrails (blokkaa vähintään 5 vaarallista komentoa), 4) Testaa 5 eri tehtävällä, 5) Dokumentoi mitä agentti osasi ja missä se epäonnistui.
Yhteenveto
- Agentin rakentaminen on 5 vaihetta: prompt, työkalut, guardrails, suoritus, testaus
- System prompt määrittelee agentin persoonallisuuden ja rajat
- Guardrails suojaavat vaarallisilla toiminnoilta
- Testaa monipuolisesti: tiedon haku, monivaiheinen tehtävä, turvallisuus
- Seuraavaksi opimme muistimalleja ja RAG:ia agenteille