AI Engineering Academy · Lektion

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.

Lektion 3 av 413 steg

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 convenience

Behö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 anomalies

Tokenfö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 sessions

Testa 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.

Gratis att börja

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

  1. Taxonomi för promptinjektionsattacker
  2. Försvara RAG-system mot injektioner
  3. Säkra verktygsåtkomst för agenter
  4. Genomför red teaming av er LLM-applikation
← Tillbaka till AI Engineering Academy