Säkra verktygsåtkomst för agenter
Tillämpa principer om minsta privilegium på agenters verktygsbehörigheter, implementera bekräftelsesteg före destruktiva åtgärder och granska agenternas åtgärdsloggar för att upptäcka avvikande beteende.
Säkra verktygsåtkomst för agenter är en gratis lektion i AI Engineering Academy på CoddyKit. Detta är lektion 3 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för AI Engineering Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i AI Engineering Academy innehåller totalt 4 lektioner.
Säkerhetsproblemet med verktygsåtkomst
När du ger en AI-agent ett verktyg ger du den möjlighet att utföra handlingar i den verkliga världen. Ett verktyg som skickar e-post, kör SQL-frågor, anropar betalnings-API:er eller ändrar filer kan orsaka betydande skada om agenten komprometteras genom promptinjektion eller helt enkelt gör ett misstag. Att skydda agentbaserad verktygsåtkomst innebär att utforma verktygslagret så att skadan från varje enskild verktygsanvändning begränsas, kan granskas och, där det är möjligt, kan återställas.
Principen om minsta privilegium
Tillämpa principen om minsta privilegium på varje verktyg: ge agenten den minsta åtkomst som krävs för att slutföra den tilldelade uppgiften, och inget mer. Om agenten behöver läsa kunduppgifter ska den få en skrivskyddad databasanslutning — inte den fullständiga administratörsanslutning som du använder för underhåll. Om den skickar aviseringar ska dess API-nyckel begränsas till enbart aviseringsslutpunkten. Minsta privilegium begränsar konsekvenserna av varje säkerhetsincident.
from enum import Enum
from dataclasses import dataclass
class Permission(Enum):
READ_CUSTOMER_PROFILE = 'read_customer_profile'
SEND_NOTIFICATION = 'send_notification'
READ_ORDER_HISTORY = 'read_order_history'
WRITE_CUSTOMER_PROFILE = 'write_customer_profile' # higher privilege
PROCESS_REFUND = 'process_refund' # highest risk
@dataclass
class AgentIdentity:
agent_id: str
allowed_permissions: set[Permission]
# Support chat agent: read-only + send notification only
SUPPORT_AGENT = AgentIdentity(
agent_id='support-agent-v1',
allowed_permissions={
Permission.READ_CUSTOMER_PROFILE,
Permission.READ_ORDER_HISTORY,
Permission.SEND_NOTIFICATION # can notify, but NOT write or refund
}
)
# NOT: give every agent all permissions for convenienceBehörighetsstyrd körning av verktyg
Tillämpa minsta privilegium på körningsnivån, inte bara på designnivån. Varje verktygsanrop måste gå genom en behörighetskontroll som verifierar att den anropande agenten har den behörighet som krävs för den specifika åtgärden. Detta kan inte kringgås av agenten eller av en promptinjektion, eftersom det upprätthålls i kod och inte i LLM:ens prompt.
class ToolGateway:
def __init__(self, agent: AgentIdentity):
self.agent = agent
self.audit_log = []
def execute_tool(self, tool_name: str, required_permission: Permission, tool_fn, **kwargs) -> dict:
# Permission check - enforced in code, not in the LLM prompt
if required_permission not in self.agent.allowed_permissions:
self.log_denied(tool_name, required_permission, kwargs)
raise PermissionError(
f'Agent {self.agent.agent_id} does not have permission: {required_permission.value}'
)
# Execute tool
result = tool_fn(**kwargs)
self.log_allowed(tool_name, kwargs, result)
return result
def log_denied(self, tool: str, permission: Permission, args: dict):
entry = {'type': 'DENIED', 'agent': self.agent.agent_id, 'tool': tool, 'permission': permission.value, 'args': args}
self.audit_log.append(entry)
print(f'SECURITY: Permission denied - {entry}')
def log_allowed(self, tool: str, args: dict, result):
entry = {'type': 'ALLOWED', 'agent': self.agent.agent_id, 'tool': tool, 'args': args}
self.audit_log.append(entry)
gateway = ToolGateway(SUPPORT_AGENT)
# This will succeed (agent has READ permission)
gateway.execute_tool('read_profile', Permission.READ_CUSTOMER_PROFILE, read_customer_profile, user_id='123')
# This will raise PermissionError (agent lacks PROCESS_REFUND permission)
gateway.execute_tool('process_refund', Permission.PROCESS_REFUND, process_refund, order_id='456', amount=50.00)Bekräftelsesteg för destruktiva åtgärder
Vissa åtgärder är oåterkalleliga eller har stor påverkan: att ta bort poster, skicka massutskick och behandla finansiella transaktioner. Kräv uttrycklig mänsklig bekräftelse innan agenten utför en sådan åtgärd. Agenten föreslår åtgärden (vad den vill göra och varför), en människa godkänner eller avslår den, och först därefter fortsätter körningen. Denna bekräftelsegrind är det enskilt mest effektiva skyddet mot agentfel och missbruk som drivs av injektioner.
HIGH_RISK_ACTIONS = {
'delete_customer_record',
'send_bulk_email',
'process_refund_over_100',
'deploy_code',
'revoke_user_access'
}
def execute_with_confirmation(tool_name: str, tool_args: dict, agent_reasoning: str) -> dict:
if tool_name in HIGH_RISK_ACTIONS:
# Pause and request human approval
approval_request = {
'action': tool_name,
'arguments': tool_args,
'agent_reasoning': agent_reasoning,
'risk_level': 'HIGH'
}
approval = request_human_approval(approval_request) # blocks until human responds
if not approval.approved:
return {'status': 'rejected', 'reason': approval.rejection_reason}
# Log the approval for audit trail
log_approval(tool_name, tool_args, approved_by=approval.approver_id)
# Execute only after confirmation
return execute_tool(tool_name, **tool_args)Avgränsning av verktyg: tid, användare och data
Utöver behörighetstyper bör du avgränsa verktygsåtkomst längs tre dimensioner. Tidsgränser: API-nycklar eller token som upphör att gälla när agentens session avslutas. Användargränser: en agent som hjälper användare A får aldrig komma åt användare B:s data, även om agenten instrueras att göra det. Datagränser: en kundsupportagent bör endast få åtkomst till uppgifterna för den kund som den för närvarande hjälper, inte alla kunder. Implementera dessa gränser i verktygens implementationer, inte i agentens promptar.
class ScopedCustomerTool:
def __init__(self, current_user_id: str, session_token: str):
self.user_id = current_user_id # agent can only access THIS user's data
self.token = session_token # expires at end of session
def get_customer_profile(self) -> dict:
# Hardcoded to current user - agent cannot change this via prompt
return db.query(
'SELECT * FROM customers WHERE id = %s',
(self.user_id,) # parameterized, always this user's ID only
)
def get_order_history(self, limit: int = 10) -> list:
# Even if the agent says 'get orders for user 999', it gets self.user_id
return db.query(
'SELECT * FROM orders WHERE customer_id = %s ORDER BY date DESC LIMIT %s',
(self.user_id, min(limit, 50)) # cap limit too
)
# Inject scoped tool into agent - cannot be overridden by prompt
def create_support_agent(user_id: str, session_token: str):
scoped_tools = ScopedCustomerTool(user_id, session_token)
return AgentExecutor(llm=llm, tools=[scoped_tools.get_customer_profile, scoped_tools.get_order_history])Indatavalidering av verktygsargument
Agenter genererar verktygsargument som text. Innan något verktyg körs ska alla argument valideras mot ett strikt schema. Detta förhindrar: SQL-injektion via verktygsparametrar, sökvägshanteringsattacker (där agenten skickar '../../../etc/passwd' som filsökväg), SSRF-attacker (där agenten skickar en intern tjänste-URL som parametern 'remote URL') samt heltalsöverflöden eller värden utanför tillåtet intervall som kan orsaka oväntat beteende.
from pydantic import BaseModel, validator, constr, confloat
import re
class SendEmailArgs(BaseModel):
to: str
subject: constr(max_length=200)
body: constr(max_length=10000)
@validator('to')
def must_be_company_email(cls, v):
if not re.match(r'^[^@]+@(?:yourcorp\.com|partner\.com)$', v):
raise ValueError('Email must be sent to yourcorp.com or partner.com domains only')
return v
class ReadFileArgs(BaseModel):
filename: constr(pattern=r'^[a-zA-Z0-9_\-\.]+$') # alphanumeric only, no path traversal
@validator('filename')
def no_parent_directory(cls, v):
if '..' in v or '/' in v or '\\' in v:
raise ValueError('Path traversal detected')
return v
# Validate before execution
def validated_send_email(args_dict: dict) -> dict:
args = SendEmailArgs(**args_dict) # raises ValueError on invalid input
return send_email(args.to, args.subject, args.body)Oföränderlig granskningsloggning
Varje verktygsanrop som görs av en agent måste loggas i en oföränderlig granskningslogg. Loggposten måste innehålla: agent-ID och sessions-ID, verktygets namn och alla argument, returvärdet, tidsstämpeln samt agentens angivna motivering till anropet. Oföränderlig innebär att agenten (eller en angripare) inte kan ta bort eller ändra loggposter. Använd lagring som endast tillåter tillägg (molnloggtjänster, databaser med engångsskrivning eller WORM-lagring).
import hashlib
import json
import time
class ImmutableAuditLog:
def __init__(self, log_backend):
self.backend = log_backend # e.g., CloudWatch, BigQuery, or append-only file
self.previous_hash = '0' * 64 # genesis hash
def record(self, agent_id: str, tool_name: str, args: dict, result, reasoning: str):
entry = {
'agent_id': agent_id,
'tool': tool_name,
'args': args,
'result_summary': str(result)[:500], # truncate large results
'reasoning': reasoning[:1000],
'timestamp': time.time(),
'previous_hash': self.previous_hash # chain entries like a blockchain
}
entry_json = json.dumps(entry, sort_keys=True)
entry['hash'] = hashlib.sha256(entry_json.encode()).hexdigest()
self.backend.append(entry) # append-only, never update
self.previous_hash = entry['hash']
return entry['hash']Upptäcka avvikande agentbeteende
Även med behörighetsgrindar och granskningsloggar bör du bevaka mönster av avvikande beteende som tyder på att en agent har komprometterats eller beter sig oväntat. Signaler på avvikelser omfattar: att en supportagent plötsligt anropar verktyg som den aldrig tidigare har anropat, en ovanlig ökning av antalet verktygsanrop från en agent, argument som på misstänkta sätt avviker från det normala (ovanligt långa strängar eller märkliga teckensekvenser) eller anrop som sker på ovanliga tider.
from collections import Counter
class AgentBehaviorMonitor:
def __init__(self):
self.tool_call_counts = Counter() # tracks historical tool usage
self.arg_length_history = {} # tracks typical argument lengths
def record_and_check(self, agent_id: str, tool_name: str, args: dict) -> list[str]:
key = f'{agent_id}:{tool_name}'
anomalies = []
self.tool_call_counts[key] += 1
# Flag tools never called before by this agent
if self.tool_call_counts[key] == 1 and tool_name not in COMMON_TOOLS:
anomalies.append(f'First time agent {agent_id} called unusual tool: {tool_name}')
# Flag unusually long arguments (potential injection payload)
total_arg_length = sum(len(str(v)) for v in args.values())
if tool_name not in self.arg_length_history:
self.arg_length_history[tool_name] = []
self.arg_length_history[tool_name].append(total_arg_length)
if len(self.arg_length_history[tool_name]) > 10:
avg = sum(self.arg_length_history[tool_name]) / len(self.arg_length_history[tool_name])
if total_arg_length > avg * 5:
anomalies.append(f'Unusually long arguments for {tool_name}: {total_arg_length} chars (avg: {avg:.0f})')
return anomaliesTokenförfall och sessionsavgränsning
Agentsessioner bör ha en definierad livslängd. Utfärda kortlivade token eller autentiseringsuppgifter till agenten när en session startar och återkalla dem när sessionen avslutas. Om en agents session komprometteras under körningen begränsas angriparens möjlighet att utnyttja den komprometterade sessionen av tokenets giltighetstid. Sessionsavgränsning säkerställer också att en enda komprometterad agent inte kan användas för uppföljningsattacker flera dagar senare.
import secrets
import time
class SessionTokenManager:
def __init__(self, ttl_seconds=3600):
self.tokens = {} # token -> (agent_id, user_id, expires_at)
self.ttl = ttl_seconds
def issue_token(self, agent_id: str, user_id: str) -> str:
token = secrets.token_urlsafe(32)
expires_at = time.time() + self.ttl
self.tokens[token] = (agent_id, user_id, expires_at)
return token
def validate_token(self, token: str) -> dict | None:
if token not in self.tokens:
return None
agent_id, user_id, expires_at = self.tokens[token]
if time.time() > expires_at:
del self.tokens[token] # clean up expired token
return None
return {'agent_id': agent_id, 'user_id': user_id}
def revoke_token(self, token: str):
self.tokens.pop(token, None)
token_manager = SessionTokenManager(ttl_seconds=1800) # 30-minute sessionsTesta verktygssäkerhet
Testa ditt verktygssäkerhetslager genom att simulera attacker: försök anropa ett begränsat verktyg med en obehörig agent, ange argument med sökvägshantering, injicera instruktionssträngar i verktygsparametrar och försök anropa verktyg med utgångna token. En heltäckande testsvit för verktygssäkerhet bör omfatta alla behörighetsgränser, alla valideringsregler och alla utlösare för avvikelsedetektering.
Utforma för återställningsbarhet
Där det är möjligt bör du utforma verktyg så att de är återställningsbara eller stegvisa. I stället för att omedelbart ta bort en post kan du markera den som borttagen med en tombstone så att den kan återställas. I stället för att skicka ett e-postmeddelande omedelbart kan du lägga det i en kö för 'pending send' som körs efter ett granskningsfönster på 5 minuter. Stega finansiella transaktioner genom att hålla dem inne innan de slutregleras. Återställningsbarhet eliminerar inte säkerhetsrisken, men minskar kraftigt konsekvenserna av framgångsrika attacker.
Snabbkontroll
Testa din förståelse av hur man skyddar agentbaserad verktygsåtkomst från den här lektionen.
Lektionssammanfattning
I den här lektionen lärde du dig att principen om minsta privilegium begränsar verktygsbehörigheter till det som varje agentroll faktiskt behöver, att behörighetsgrindar på kodnivå upprätthåller dessa behörigheter på ett sätt som inte kan kringgås av promptinjektion, och att mänskliga bekräftelsesteg för åtgärder med hög risk utgör ett sista säkerhetsnät innan oåterkalleliga operationer körs. Härnäst genomför vi en strukturerad red-team-övning för LLM-applikationer.
Lär dig Python med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 30
- Lektioner
- 120
Vanliga frågor
Är lektionen ”Säkra verktygsåtkomst för agenter” gratis?
Ja – hela texten till ”Säkra verktygsåtkomst för agenter” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i AI Engineering Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i AI Engineering Academy innehåller totalt 4 lektioner.
Vad lär jag mig i ”Säkra verktygsåtkomst för agenter”?
Tillämpa principer om minsta privilegium på agenters verktygsbehörigheter, implementera bekräftelsesteg före destruktiva åtgärder och granska agenternas åtgärdsloggar för att upptäcka avvikande betee… Ni övar på AI Engineering Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig AI Engineering Academy?
Du behöver inga förkunskaper. Utbildningen i AI Engineering Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 3 av 4.
Hur lång tid tar lektionen ”Säkra verktygsåtkomst för agenter”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här AI Engineering Academy-lektionen?
Ja. Varje AI Engineering Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Taxonomi för promptinjektionsattacker
- Försvara RAG-system mot injektioner
- Säkra verktygsåtkomst för agenter
- Genomför red teaming av er LLM-applikation