Agentic AI

Zwei Systeme, ein Vertriebsprozess: Ein AWS-Partner-Agent auf Amazon AgentCore Harness

20 min Lesezeit
· Zuletzt aktualisiert: 31. August 2026
Zwei Systeme, ein Vertriebsprozess: Ein AWS-Partner-Agent auf Amazon AgentCore Harness

Hinweis: Dieser Artikel wurde mit Unterstützung von KI aus dem englischen Original übersetzt.

TL;DR: Ich habe auf AWS Bedrock AgentCore Harness (mit Claude Sonnet 5) einen Chat-Agent gebaut, der HubSpot und AWS Partner Central verbindet, damit Sales-Reps Opportunity-Daten nicht mehr manuell zwischen beiden Systemen abtippen müssen — ein Rep tippt einen Firmennamen, der Agent findet die passende Partner-Central-Opportunity, qualifiziert sie anhand der BANT-Kriterien, beantwortet Fragen aus einer Knowledge Base und schreibt nach expliziter menschlicher Freigabe einen Kontakt zurück nach HubSpot. Jeder Tool-Call läuft über ein einziges Gateway mit Cedar-Policy-Enforcement, sodass die Reichweite des Modells in beide Live-Systeme überprüfbar bleibt, statt in einem Prompt-Text vergraben zu sein.

Teil 1 der Serie „Einen Partner-Sales-Agent auf Amazon Bedrock AgentCore bauen“, aufgebaut um ein reales Projekt: ein dialogbasierter Agent, der HubSpot CRM und AWS Partner Central für das Sales-Team eines AWS-Partners verbindet. Alles, was hier beschrieben wird, ist deployed und läuft produktiv. Der Aufbau dahinter ist mit Terraform automatisiert, aber nichts in dieser Serie erfordert das: Jede gezeigte Fähigkeit lässt sich auch über die AWS Management Console einrichten. Dieser Artikel konzentriert sich auf die allgemeine Architektur der Demo.

Inhaltsverzeichnis

Als Unternehmen, das mit IT-Produkten, Professional Services und Managed Services arbeitet, brauchen Sie ein zentrales Customer-Relationship-Management (CRM), das mit Ihren Marketing- und Sales-Prozessen verbunden ist. Diese Informationen umfassen üblicherweise Kontakte, Deals, Notizen, Follow-up-Aufgaben, Marketingkampagnen und vieles mehr. Der gesamte Vertriebsprozess lebt hier. Ein neuer Lead kommt über eine Kampagne herein, bekommt einen Kontakt-Datensatz, durchläuft Deal-Stages, und jeder Touchpoint landet im selben CRM, aus dem auch das Marketing-Team berichtet. CRM-Systeme sind auf die eigenen Prozesse des Unternehmens zugeschnitten und unterscheiden sich, wenn man zwei ähnliche Unternehmen vergleicht. Es gibt mehrere etablierte CRM-Tools am Markt, von denen Sie einige vermutlich kennen: Salesforce, Microsoft Dynamics, HubSpot.

Ich nutze aktuell HubSpot, deshalb sehen Sie in dieser Artikelserie praktische Beispiele für HubSpot — sie lassen sich aber gleichwertig auf jedes andere CRM übertragen.

Wenn Sie als AWS-Partner Amazon-Web-Services-Lösungen im Co-Sell vertreiben, bekommen Sie den langen Arm des AWS-CRM zu spüren: AWS Partner Central. Das Portal ist das zentrale Einfallstor für AWS-Marketing- und Sales-Prozesse. AWS verfolgt dieselbe Kundenbeziehung auf seiner Seite als Partner-Central-Opportunity. Dieser Datensatz trägt die Felder, die für AWS beim Co-Selling relevant sind: den Kunden, den Workload, Budget-Signale, einen Zieltermin und das AWS-Account-Team, das dem Deal zugeordnet ist. Für einen Partner im Co-Sell-Prozess ist es keine optionale Fleißarbeit, diesen Datensatz aktuell zu halten. Nur so weiß die AWS-Seite, dass der Deal existiert, wie er an die richtigen Personen weitergeleitet wird, und es ist Teil davon, wie die Partnerschaft selbst gemessen wird.

Als AWS Alliance Lead (der sich genau um die Partnerschaft mit AWS kümmert) oder als Sales-Kollege ist es eine Pflichtaufgabe für einen effektiven Vertriebsprozess, die CRM-Welt des Unternehmens und die AWS-Welt synchron zu halten. Mit wachsender Organisation und wachsendem Sales-Volumen kann dieser Sync schnell zum Flaschenhals werden. In der Vergangenheit gab es einige Connectoren (etwa für Salesforce und Microsoft Dynamics), aber sie waren kaum nutzbar und bei stark angepassten CRMs wenig flexibel.

Ein konkretes Beispiel: Ein Sales-Rep, der eine von AWS stammende Opportunity qualifiziert, hat sowohl das CRM als auch AWS Partner Central offen. Er liest Opportunity-Felder in Partner Central, tippt die relevanten Teile erneut in HubSpot ein und kopiert die Notizen, die er zuletzt an die AWS-Seite gemeldet hat. Jeder manuelle Sprung ist eine Gelegenheit für die Datensätze, auseinanderzudriften. Die Kosten sind nicht nur doppelte Dateneingabe. Es ist ein Co-Sell-Prozess, der auf veralteten Informationen läuft, und ein Rep, der irgendwann leise aufhört, das System zu pflegen, das nicht sein tägliches Werkzeug ist.

Warum das jetzt und auf diese Weise lösen? Partner Central Version 3 ist seit re:Invent 2025 live [1], und seine Opportunity-Daten sind programmatisch erreichbar, unter anderem über einen dedizierten AWS Partner Central MCP-Server [2]. Das ist die Integrationsfläche, auf der dieses Projekt aufbaut. Die AWS-Seite des Workflows hat aufgehört, ein Portal zu sein, in das man sich einloggt, und ist zu etwas geworden, das ein Agent aufrufen kann.

Eine Anmerkung dazu, für wen diese Serie gedacht ist: Cloud-Engineers und AWS-Partner, die Amazon Bedrock AgentCore genau für diese Art von Integrationsproblem evaluieren. Sie setzt voraus, dass Sie IAM kennen und die grundsätzliche Form einer LLM-Tool-Calling-Loop verstehen. Sie ist keine Einführung in das, was ein KI-Agent ist, und argumentiert nirgends dafür, dass Sie einen wollen sollten. Was Sie am Ende dieses Artikels können sollten: auf Ihr eigenes Paar unverbundener Systeme schauen und beurteilen, ob es zu derselben Form passt, für die diese Architektur gebaut wurde: zwei lebende Systems of Record, ein dialogbasierter Workflow, der beide umspannt, und die harte Anforderung, dass der Zugriff des Modells auf jedes davon überprüfbar bleibt.

Was ich beweisen wollte

Eine einzige Chat-Konversation soll den gesamten Ablauf tragen. Ein Sales-Rep tippt einen Firmennamen. Der Agent findet die passende Partner-Central-Opportunity, qualifiziert sie anhand der BANT-Kriterien (Budget, Authority, Need, Timeline), beantwortet Kompetenzfragen aus einer Dokumenten-Knowledge-Base, die sowohl AWS-Dokumente als auch internes Sales-Enablement-Material enthält, schlägt einen HubSpot-Kontakt vor, wartet auf eine explizite menschliche Freigabe und schreibt den Kontakt mit einer Rückreferenz auf die Ursprungs-Opportunity nach HubSpot.

Diese Konversation ist die Demo in Artikel 7, live gegen echte HubSpot- und Partner-Central-Instanzen ausgeführt. Die sechs Artikel davor liefern die Belege für diesen Anspruch, einen Baustein nach dem anderen.

Der Stack in Kürze: Der Agent läuft auf AgentCore Harness, AWS' verwalteter Agent-Loop, inzwischen generell verfügbar [3]. Das Modell ist Claude Sonnet 5 auf AWS Bedrock. Alles läuft als verwalteter Service in einem einzigen AWS-Account in eu-central-1: kein Kubernetes, keine selbstverwaltete Inferenz und nichts, was ein Leser mit Zugriff auf die AWS Management Console nicht nachbauen könnte. Mein eigener Build automatisiert das komplette Setup mit Terraform, was sich bei Reproduzierbarkeit und Change-Review auszahlt, aber das ist ein Bonus, keine Voraussetzung. Jeder Artikel nennt, was zu konfigurieren ist und welche Werte wichtig sind, sodass auch ein reiner Konsolen-Leser jeden Schritt nachvollziehen kann.

Die reale Anwendung

Die Architektur, von oben nach unten

Jetzt zum besten Teil: das Architekturdiagramm. Es ist ein Überblick über das gesamte System. Der Rest dieses Artikels geht es Region für Region durch, und der Rest der Serie zoomt in jeweils eine Region pro Artikel hinein.

Ein Architektur-Überblick

Lesen Sie es in vier horizontalen Bändern: statische Content-Auslieferung (CloudFront, S3), dynamischer Content (Cognito, API Gateway, Lambda-Funktionen), AgentCore (Harness, Memory, Gateway, Policy Engine) und die Tool-Ebene (sechs Targets, drei Lambdas, eine Knowledge Base, drei externe Systeme). Eine Nutzeranfrage kommt links herein, und jeder externe Effekt verlässt das System unten, durch genau ein Gateway.

Statisches Hosting

Das Frontend ist eine statisch exportierte Next.js-Chat-UI. Es gibt nirgends einen Next.js-Server: Der Build erzeugt reine Dateien, und Konfigurationswerte wie die Cognito-Client-ID und der API-Endpunkt werden zur Build-Zeit ins Bundle eingebacken, weil ein statischer Export zur Request-Zeit keinen Server hat, der Umgebungsvariablen lesen könnte.

Diese Dateien liegen in einem privaten S3-Bucket mit vollständig blockiertem öffentlichen Zugriff, ausgeliefert ausschließlich über CloudFront mit Origin Access Control. Die Bucket-Policy gewährt s3:GetObject ausschließlich dem CloudFront-Service-Principal, bedingungsgebunden auf die ARN genau dieser Distribution, und sie vergibt bewusst niemals s3:ListBucket. Diese Auslassung hat einen sichtbaren Nebeneffekt, den man kennen sollte: Eine Anfrage nach einem fehlenden Objekt liefert 403 statt 404, weil S3 ohne List-Berechtigung sich weigert zu bestätigen, dass ein Objekt nicht existiert. Beide Statuscodes werden in den Custom-Error-Responses der Distribution auf /index.html gemappt, genau das, was eine Single-Page-App für funktionierende Deep-Links braucht. Was diese Region beweist: Das Frontend ist eine ganz normale statische Site ohne Server-Side-Rendering. Jeder dynamische Aufruf läuft über den als Nächstes beschriebenen „Dynamic Content". Die Serie widmet dieser Region keinen eigenen Artikel, weil nichts daran AgentCore-spezifisch ist und es sich um ein etabliertes Muster handelt.

Dynamic Content: Cognito, API Gateway und ein Streaming-Relay

Ein Ausschnitt der Content-Delivery-Architektur

Endnutzer authentifizieren sich gegen einen Cognito-User-Pool. Der Frontend-App-Client ist public ohne Client-Secret, weil eine Browser-SPA ohnehin kein Geheimnis bewahren kann. Ein Konfigurationsdetail hat mich eine Debugging-Session gekostet und ist es wert, weitergegeben zu werden: Bei den aktivierten Auth-Flows des Clients musste SRP hinzugefügt werden [4], weil AWS Amplifys signIn() standardmäßig den SRP-Flow nutzt und der Standard-Login-Pfad von Amplify ohne aktivierten Flow gegen einen ansonsten völlig gesunden Pool fehlschlägt.

Der Chat selbst ist ein einzelner streamender POST-Endpunkt auf einer REGIONAL REST API. Davor sitzt ein nativer COGNITO_USER_POOLS-Authorizer, der das ID-Token des Aufrufers validiert, bevor überhaupt Compute läuft. Diese Platzierung kauft eine Eigenschaft, die ich später in CloudWatch bestätigt habe: Eine abgelehnte oder nicht authentifizierte Anfrage erzeugt null abgerechnete Lambda-Invocations, weil die Ablehnung beim Authorizer passiert, nicht in Anwendungscode, den man selbst schreiben, testen und bezahlen müsste.

Hinter dem Authorizer sitzt das Streaming-Relay, und es ist die eine bewusste Ausnahme des Projekts von einer ansonsten reinen Python-Lambda-Regel: Es läuft auf Node.js, weil AWS-Lambda-Response-Streaming nur auf verwalteten Node-Runtimes verfügbar ist [5]. Die Integration nutzt die Response-Streaming-Invoke-ARN der Funktion mit dem Transfer-Modus STREAM, sodass die Ausgabe des Harness als fortlaufender Server-Sent-Events-Stream im Browser ankommt statt als ein gepuffertes Blob am Ende. Ein 90-Sekunden-Funktions-Timeout federt die First-Token-Latenz eines Turns ab, in dem das Modell mehrere Tools aufruft, bevor es zu antworten beginnt. Die andere Aufgabe des Relays ist Identität, und sie ist tragend genug, dass ihr weiter unten ein ganzer Abschnitt gewidmet ist — inklusive der Alternative, die sie ausgestochen hat.

Eine zweite, nicht-streamende Lambda bedient die unterstützenden Routen (/sessions, /preferences) hinter demselben Authorizer, gestützt auf eine kleine DynamoDB-Tabelle mit Memory-Preference-Flags pro Nutzer.

Was diese Region beweist: Authentifizierung wird an der API-Grenze erzwungen, Streaming ist eine bewusste Transport-Entscheidung und kein nachträglicher Einfall, und nichts davon brauchte AgentCore-spezifischen Code.

AWS' eigene Referenzarchitektur schlägt eine schlankere Architektur vor als meine: API Gateway und die Relay-Lambda komplett überspringen und den Browser den Harness direkt aufrufen lassen [6]. Der Harness unterstützt das über einen nativen Inbound-JWT-Authorizer. Man zeigt ihn auf eine OIDC-Discovery-URL, setzt den Cognito-App-Client auf eine Allowlist, und der Browser ruft den Harness über HTTPS mit einem einfachen Bearer-Token auf [7]; das AgentCore-SDK liefert sogar einen echten Browser-Build mit Streaming-Unterstützung. Ich habe das evaluiert und aus einem Grund verworfen. Der Authorizer sichert nur den Call selbst ab: Er validiert Signatur, Issuer und Audience des Tokens und lässt die Anfrage dann durch. Was er nicht tut: irgendeinen Claim aus diesem Token an die actorId der Anfrage binden — das Feld, nach dem AgentCore Memory Nutzer partitioniert. actorId kommt als einfaches, vom Client kontrolliertes Payload-Feld an, sodass jeder authentifizierte Nutzer den Wert eines anderen Nutzers senden und dessen Memory lesen könnte. AWS' eigene Sicherheits-Guidance sagt genau das: Nutzer-Identifikatoren aus dem authentifizierten Principal ableiten, niemals aus vom Client gelieferten Werten [8][9]. Diese Lücke zu schließen würde bedeuten, das JWT zu verifizieren und actorId im Agent-Code selbst abzuleiten. Das Relay tut genau das bereits an einer Stelle: deriveActorId() liest ausschließlich den Cognito-verifizierten sub-Claim, serverseitig, und schlägt fehl, wenn er fehlt (fail closed). Das Relay zu löschen würde diese Logik nicht entfernen, sondern sie nur an einen Ort mit weniger Trennung vom Modell verschieben.

Der AgentCore-Block: Harness, Memory, Gateway, Policy

Vier verwaltete Bausteine bilden den Agent selbst.

AgentCore Harness, seine Konfiguration und Fähigkeiten

Der Harness ist die Agent-Loop: Man übergibt ihm ein Modell, einen System-Prompt, Tools, Skills und eine Memory-Bindung, und AgentCore führt die Loop aus, die entscheidet, wann geantwortet und wann ein Tool aufgerufen wird. Der Harness dieses Projekts betreibt das LLM-Modell Claude Sonnet 5 über das Cross-Region-Inference-Profil eu.anthropic.claude-sonnet-5 auf AWS Bedrock. Der Harness ist aus genau einem Grund container-backed: Skills sind Dateisystem-Pfad-Artefakte, und ein rein deklarativer Harness hat kein Dateisystem, auf das man sie legen könnte, deshalb liefert das Projekt die BANT-Qualifizierungs-Skill eingebacken in ein Container-Image in ECR aus. Die beiden anderen Optionen zum Hosten von Skills (auf S3 oder in einem Git-Repository) wurden vom Terraform-AWS-Provider zum Zeitpunkt der Demo-Erstellung nicht unterstützt [11].

AgentCore Memory gibt der Loop kurzfristige Session-Events plus vier Langzeit-Memory-Strategien, was es einem Nutzer erlaubt, den Browser zu schließen, zurückzukommen und dort weiterzumachen, wo er aufgehört hat.

Das Gateway ist der einzige MCP-Endpunkt, über den der Harness Tools aufruft, und die Cedar-Policy-Engine (auch in Amazon Verified Permissions genutzt) ist im ENFORCE-Modus an dieses Gateway gebunden und bewertet jeden einzelnen Call, bevor er ein Target erreicht.

Die strukturelle Entscheidung, die alles andere im Diagramm prägt: Jeder externe Seiteneffekt, den das Modell erzeugen kann, läuft über dieses eine Gateway. Welche Tools das Modell überhaupt sehen kann, ist eine Allowlist auf dem Harness. Ob ein bestimmter Call überhaupt durchgeht, ist eine Cedar-Regel. Das Ziel dieser Implementierung ist es, den Blast Radius eines fehlverhaltenden oder manipulierten Modells zu reduzieren und es an eine überprüfbare Konfiguration zu binden — nicht nur an einen System-Prompt-Text.

Den Harness mit diesem Gateway zu verdrahten ist ein kleiner Konfigurationsschritt: Am Harness ein Tool vom Typ Gateway hinzufügen, es auf das Gateway zeigen lassen und die Outbound-Authentifizierung auf IAM setzen.

Zwei Details hier geben einen Vorgeschmack auf spätere Artikel, und sie gelten identisch, egal ob Sie das in der Konsole oder im Code konfigurieren. Der Tool-Name pc ist bewusst knapp: AWS deckelt jeden Tool-Permission-Glob-String auf 64 Zeichen, und der Tool-Name ist Teil jedes Globs, also ist jedes Zeichen, das für einen hübschen Namen ausgegeben wird, ein Zeichen, das den Tool-Namen fehlt, die er matchen muss. Ein späterer Artikel beschreibt, wie ich das herausgefunden habe — dabei erzählte das Modell in Prosa vollständig fiktive Tool-Calls, die mit null echten Tools übereinstimmten. Outbound-Authentifizierung auf IAM gesetzt bedeutet, dass der Harness seine eigenen Gateway-Calls mit den Credentials seiner Execution Role signiert. In diesem Projekt gibt es bewusst keine OAuth-Konfiguration und nirgends eine AgentCore-Identity-Ressource, weil das für diese Demo-Architektur nicht nötig war — in anderen Setups kann es aber sinnvoll sein. Was diese Region beweist: Das Urteilsvermögen des Modells ist nicht das Einzige, was zwischen dem Prompt eines Nutzers und einem Live-CRM-Write steht.

AWS Management Console für AgentCore

Sechs Gateway-Targets hinter einer Tür

Ein „Single Gateway" bedeutet nicht „ein Tool". Es bedeutet einen Weg hinaus in sechs kontrollierte Targets:

TargetBackendWas das Modell bekommt
list-oppsPartner-Central-Lambdalist_matching_opportunities: Opportunities per Firmenname finden
get-oppPartner-Central-Lambdaget_opportunity: der vollständige Datensatz plus eine BANT-Source-Ansicht
reasonReasoning-Lambdareason_about: offene Fragen gegen den Partner-Central-MCP-Server
hs-searchHubSpot-Lambdasearch_contact: einen Kontakt nachschlagen, bevor ein Write vorgeschlagen wird
hs-writeHubSpot-Lambdaupsert_contact: der einzige Write-Pfad im gesamten System
managed-kbKnowledge-Base-ConnectorRetrieve und AgenticRetrieveStream: fundierte Dokumentensuche

Einige davon tragen Details, die man schon auf Kartenebene kennen sollte. Das Tool get-opp liefert die Opportunity plus eine bant_source_fields-Ansicht, in der jedes fehlende Feld als der wörtliche String "Not stated in opportunity data" gerendert wird: Die Qualifizierung, die das Modell später erstellt, muss zwischen Beleg und Fehlen unterscheiden, und dieser Vertrag wird in der Ausgabe des Tools selbst erzwungen, statt dem Ermessen des Modells überlassen zu bleiben. Das hs-write-Target wird von einer Cedar-Regel bewacht, die jeden Call ohne explizites Bestätigungs-Flag ablehnt — ein späterer Artikel seziert das genauer, inklusive dem, was dieser Guard ehrlicherweise verifiziert und was nicht. Das managed-kb-Target ist aus Sicht der Konsole ein ganz gewöhnliches Gateway-Target.

Die naheliegende Architekturfrage: Sowohl HubSpot als auch Partner Central liefern eigene MCP-Server aus — warum ist dann jedes Target eine Lambda statt einer direkten MCP-Verbindung? Zwei unterschiedliche Blocker, und sie zu benennen lohnt sich, weil sie generalisieren.

  1. Der MCP-Server von HubSpot verlangt OAuth Authorization Code mit PKCE, was zur Build-Zeit mit einem offenen AgentCore-Identity-Bug für benutzerdefinierte OAuth2-Provider kollidierte [10]
  2. Der MCP-Server von Partner Central spricht einen sendMessage/getSession-Transport, der nicht zum Session-Handshake des Gateways passt — ein echter Protokoll-Mismatch, den keine Konfiguration überbrücken kann; also macht die Reasoning-Lambda den SigV4-signierten MCP-Call selbst, ein Hop, und das Gateway routet zur Lambda. Ein zukünftiger Artikel löst beide Geschichten vollständig auf, inklusive der Outbound-Auth-Support-Matrix, die unabhängig davon dasselbe Design erzwingt.

Was diese Region beweist: Ein kontrollierter Lambda-Wrapper ist kein Eingeständnis, dass eine MCP-Integration gescheitert ist. Er ist häufig der einzige Weg, der Auth-, Transport- und Review-Anforderungen gleichzeitig erfüllt.

Die dahinterliegenden Lambdas

Jeder Tool-Call endet in einem Stück Infrastruktur mit einer eigenen, eng begrenzten IAM-Rolle, nicht in Code, der im Harness eingebettet ist. Dieser Satz klingt offensichtlich und ist das stille Rückgrat der gesamten Security-Geschichte.

Drei Lambda-Funktionen stützen die fünf Gateway-Targets. Die Partner-Central-Lambda enthält zwei deterministische Opportunity-Tools. Die Reasoning-Lambda enthält das offene reason_about-Tool und ist der einzige Principal im Workload-Account, der eine Cross-Account-Rolle in den PartnerCentral-AWS-Account annehmen kann. Die HubSpot-Lambda enthält beide HubSpot-Tools und ist der einzige Principal, der das in AWS Secrets Manager gespeicherte HubSpot-Token lesen kann. Das reduziert die Angriffsfläche, falls eine andere Komponente kompromittiert wird.

Hier zeigt sich auch die Identitätsgrenze des Harness selbst. Der Harness läuft als eine Rolle, die Modell-Calls, Memory-Zugriff und das Signieren von Gateway-Requests abdeckt. Er hat keinen HubSpot-Scope, keinen Partner-Central-Scope und keinen Secrets-Manager-Scope. Fähigkeit liegt beim Tool, nicht beim Agent, also ist das Gewähren einer neuen Fähigkeit an den Agent eine eng begrenzte Änderung an der Rolle einer Lambda, die für sich allein überprüfbar ist — egal ob Sie Rollen in der Konsole oder im Code verwalten.

Die externen Systeme

Zwei lebende Systeme sitzen am unteren Rand des Diagramms, und keines davon ist ein Mock.

HubSpot ist eine echte Demo-CRM-Instanz, erreicht über ihre REST-API mit einem Private-App-Token, das genau zwei Scopes trägt: Contacts lesen und Contacts schreiben.

Partner Central ist das echte AWS-seitige System, erreicht über seinen MCP-Server. Sein Client ist fest auf us-east-1 gepinnt, weil Partner Central keinen eu-central-1-Endpunkt anbietet — ein Mismatch mit der Region des restlichen Demo-Stacks. AWS-Cross-Account-Zugriff: Die beiden Partner-Central-seitigen Lambda-Rollen des Demo-Accounts übernehmen eine einzelne, read-only IAM-Rolle im Partner-Central-AWS-Account. Das Berechtigungsset dieser Rolle bleibt bewusst eng und trägt keinerlei Write-Actions: Dieser Agent kann Opportunities lesen und über sie nachdenken, aber er kann sie auf der AWS-Seite strukturell nicht erstellen oder verändern.

Was diese Region beweist: Die Demo arbeitet mit zwei echten externen Systemen mit realen Credentials und realen Fehlermodi — und genau daher kamen die meisten Überraschungen des Builds.

Warum in diesem Diagramm keine Datenbank steckt

Schauen Sie sich das Diagramm noch einmal an und bemerken Sie, was fehlt. Keine Aurora. Keine OLTP-Datenbank. Kein Vektor-Store. Die einzige DynamoDB-Tabelle enthält boolesche Preference-Flags. Für ein System, das Sales-Daten liest, qualifiziert und schreibt, ist diese Abwesenheit die zweitgrößte Architekturentscheidung nach dem Gateway-Flaschenhals.

Die Überlegung: HubSpot und Partner Central sind bereits die Systems of Record für ihre eigenen Daten. Einen dritten Store zu bauen, der sie spiegelt, würde exakt das Synchronisationsproblem neu erschaffen, das der Agent eigentlich beseitigen soll, und würde Schema, Migrationen, Backups und einen Sync-Job brauchen, um ehrlich zu bleiben. Die Demo-Architekturreferenz ist explizit darin, dass ein unabhängiges System of Record bewusst außerhalb des Scopes ausgeschlossen wurde: Der Agent arbeitet auf den beiden lebenden Systemen, und die einzigen Daten, die dieses Projekt tatsächlich besitzt, sind ein Ordner voller Dokumente.

Diese Dokumente — AWS-Partner-Central-Material plus das eigene Sales-Enablement-Material des Partners — fundieren den Agent über eine Bedrock Managed Knowledge Base. Die verwaltete Variante reduziert das gesamte Setup darauf, den Managed-Typ zu wählen und die eigenen Defaults des Service für Embedding-Modell, Chunking und Verschlüsselung zu akzeptieren. Es gibt also keinen Index zu entwerfen und keinen Retrieval-Code zu schreiben. Sie bringt außerdem einen nativen Gateway-Connector mit, was bedeutet, dass Retrieval über dasselbe Gateway in den Agent gelangt wie jedes andere Tool auch. Ein späterer Artikel zeigt das komplette Setup, inklusive der Web-Crawler-Quellen, die zusätzlich zum S3 eingesetzt werden.

Bevor Sie dieses Muster wiederverwenden, stellen Sie die Frage, von der es abhängt: Habe ich bereits Systems of Record, oder bin ich dabei, die Datenbank meines Agents zum System of Record zu machen? Diese Architektur bleibt nur deshalb so klein, weil die Antwort hier die erste war. Ein Projekt ohne vorgelagerte Systems of Record braucht eine echte Datenschicht, und kein Gateway-Diagramm lässt diese Anforderung verschwinden.

Der Weg, den ich nicht gegangen bin: den Harness direkt vom Browser aus aufrufen

Jeder Artikel dieser Serie nennt mindestens einen Pfad, den ich evaluiert und verworfen habe, mit dem konkreten Grund. Hier ist der erste. Während der Implementierung begann die Relay-Lambda wie ein zu formales Setup zu wirken. AgentCore Harness unterstützt einen nativen Inbound-JWT-Authorizer: Ihn mit einer OIDC-Discovery-URL konfigurieren, den Cognito-Client auf eine Allowlist setzen, und ein Browser kann den Harness direkt über HTTPS mit einem einfachen Bearer-Token aufrufen. Kein API Gateway, keine Relay-Lambda, zwei Infrastrukturstücke weniger. Das ist keine obskure Option. Das AgentCore-SDK wird mit einem echten Browser-Build veröffentlicht, Streaming-Responses werden beim direkten Call unterstützt, und AWS' eigene Referenzarchitekturen verdrahten Frontends genau so mit Agents [6].

Ich habe den Developer Guide sorgfältig gelesen, bevor ich irgendetwas gelöscht habe, und eine Lücke hat die Frage entschieden. Der Inbound-Authorizer authentifiziert den Call. Er verifiziert Signatur, Issuer und Audience des Tokens und lässt die Anfrage dann durch. Was er nicht tut: irgendeinen Claim aus diesem Token an die actorId der Anfrage binden — das Feld, das AgentCore Memory zwischen Nutzern partitioniert. actorId ist ein einfaches Payload-Feld, strukturell identisch, egal wie sich der Aufrufer authentifiziert hat, und nichts serverseitig verbindet es mit der Identität, die sich eingeloggt hat. AWS' eigene Sicherheitsdokumentation ist offen über den verwandten Mechanismus und beschreibt den zugehörigen User-ID-Header als opaken Identifikator, der nicht gegen eine authentifizierte Identität verifiziert wird, und schreibt genau die zu erwartende Abhilfe vor: Nutzer-Identifikatoren aus dem authentifizierten Principal ableiten, niemals aus vom Client gelieferten Werten [8].

Denken Sie die Konsequenz zu Ende. Bei direkten Browser-Calls könnte jeder authentifizierte Nutzer eine beliebige actorId ins Payload schreiben und das Memory eines anderen Nutzers lesen: dessen vergangene Session-Kontexte, dessen Präferenzen, was auch immer die Memory-Strategien angesammelt haben. Das Relay schließt das durch seine Konstruktion. Sein deriveActorId() liest ausschließlich den Cognito-verifizierten sub-Claim aus dem validierten Token, serverseitig, und schlägt fehl, wenn der Claim fehlt. Der Client ist davon unberührt und hat keine Angriffsfläche, um eine falsche actorId zu senden.

Also bleibt die Lambda-Relay bestehen, und die Entscheidung hat neu gerahmt, was das Relay eigentlich ist. Es ist kein Mittelsmann, sondern eine Komponente, die Isolation garantiert. Ich habe diese Eigenschaft live verifiziert, und ein zweiter Cognito-Nutzer, der eine gestohlene Session-ID wiedergibt, bekommt nichts vom Memory-Kontext des ersten Nutzers zu sehen.

Die übertragbare Lehre ist die Methode, nicht das Ergebnis. Die Option war real, unterstützt und von AWS selbst dokumentiert. Sie hat trotzdem gegen ein konkretes Problem verloren, nachdem die Sicherheit geprüft wurde. Manchmal ist eine Präferenz keine Entscheidung, die man treffen kann.

Übertragbare Muster

Drei Gewohnheiten aus diesem Artikel generalisieren über diese Demo hinaus auf jeden Agent-Build.

  • Ein einzelnes Gateway als Blast-Radius-Kontrolle. Jeden externen Seiteneffekt, den das Modell auslösen kann, über einen kontrollierten Endpunkt leiten, sodass das aufrufbare Tool-Set, die Berechtigungen jedes Tools und die Per-Call-Guard-Regeln alle in überprüfbarer Konfiguration liegen. Die Alternative — Fähigkeit verstreut über den eigenen Code und Prompt des Agents — hat keine Konfigurationsfläche, die man überprüfen könnte.
  • „Kein unabhängiges System of Record" als Scoping-Heuristik. Bevor Sie Ihrem Agent eine Datenbank bauen, prüfen Sie, ob die Systeme, die Sie integrieren, bereits die Systems of Record sind. Wenn ja, ist ein Spiegel-Store Scope, den Sie nicht brauchen, und ein Konsistenz-Bug, den Sie noch nicht hatten.
  • Evaluieren-und-Verwerfen als Gewohnheit. Für jede größere Design-Entscheidung die idiomatischer wirkende Alternative benennen, sie gegen die Primärdokumentation prüfen und den konkreten Grund festhalten, warum sie verloren hat. Die Inbound-Auth-Geschichte oben ist die erste dieser Serie.

Wenn Sie das nachbauen

Drei Dinge werden Sie in der ersten Stunde beißen, wenn Sie diese Architektur selbst aufbauen, ob in der Konsole oder im Code. Alle drei stammen aus der eigenen Build-Historie dieses Projekts.

Erstens sind zwei AWS-Accounts beteiligt, und nur einer davon ist Ihrer zum Automatisieren. Jede Ressource im Diagramm liegt im Workload-Account. Der Partner-Central-AWS-Account enthält genau eine erstellte, read-only IAM-Rolle, die die beiden Partner-Central-seitigen Lambda-Rollen des Workload-Accounts annehmen. Erstellen Sie diese Rolle zuerst, in der IAM-Konsole des Partner-Central-Accounts, und listen Sie beide Lambda-Execution-Role-ARNs explizit als vertrauenswürdige Principals in ihrer Trust Policy: sts:AssumeRole allein auf der Workload-Seite zu gewähren reicht nicht, und der Fehlermodus ist ein AccessDenied zur Laufzeit, lange nachdem das Setup fertig aussah.

Zweitens der Modellzugriff. Claude Sonnet 5 ist ein Marketplace-gated Bedrock-Modell, dessen Nutzungsvereinbarung einmal pro Account akzeptiert werden muss, bevor irgendein Tool-nutzender Aufruf gelingt. Ich habe das aus einer live aufgetretenen AccessDeniedException gelernt, die auf aws-marketplace:Subscribe in einer Full-Admin-Session verwies — das schloss eine IAM-Fehlkonfiguration aus und deutete auf ein tatsächlich nicht akzeptiertes Angebot hin. Akzeptieren Sie die Vereinbarung einmal (die Model-Access-Seite der Bedrock-Konsole ist der direkte Weg), stellen Sie sicher, dass die Identität, die das tut, aws-marketplace:Subscribe und aws-marketplace:ViewSubscriptions trägt, und beachten Sie, dass die Vereinbarungsmechanik in us-east-1 liegt, unabhängig von Ihrer Workload-Region. Als Bonus für automatisierungsaffine Leser: Ein kürzliches Update des AWS-Terraform-Providers erlaubt es, das mit einer Terraform-Ressource nachzubauen.

Drittens die Reihenfolge. Ein container-backed Harness referenziert ein Container-Image, das schon in ECR existieren muss, bevor der Harness selbst erstellt werden kann — ein echtes Henne-Ei-Problem auf einem frischen Account: zuerst das ECR-Repository erstellen, das Image bauen und pushen (linux/arm64 ist erforderlich) und erst dann den Harness erstellen. Ich bin darauf beim ersten Live-terraform apply gestoßen. Dieselbe Reihenfolge gilt auch in der Konsole; Automatisierung macht es nur leichter, sie in einem Schritt falsch zu machen.

Ich hoffe, dieser Artikel war hilfreich für Sie. Ich freue mich über Feedback, was Ihnen gefallen hat und was nicht, damit ich künftige Artikel verbessern kann.


Quellen

[1] Verfügbarkeit von AWS Partner Central v3. https://aws.amazon.com/de/blogs/aws/aws-partner-central-now-available-in-aws-management-console/

[2] AWS-Partner-Central-Agents begleiten neue Partner jetzt von der Registrierung bis zur Verkaufsbereitschaft . https://aws.amazon.com/about-aws/whats-new/2026/06/aws-partner-central/

[3] Allgemeine Verfügbarkeit von Amazon Bedrock AgentCore Harness. https://aws.amazon.com/about-aws/whats-new/2026/06/amazon-bedrock-agentcore-harness-generally-available/

[4] AWS-Amplify-Dokumentation: signIn() nutzt standardmäßig den SRP-Flow. https://docs.amplify.aws/react/frontend/auth/switching-authentication-flows/

[5] AWS-Lambda-Dokumentation: Response Streaming ist nur auf Node.js-Managed-Runtimes verfügbar. https://docs.aws.amazon.com/lambda/latest/dg/configuration-response-streaming.html

[6] AWS-Referenzimplementierungen des direkten Browser-zu-Agent-Musters: das Starter-Template aws-samples/sample-amazon-bedrock-agentcore-fullstack-webapp (https://github.com/aws-samples/sample-amazon-bedrock-agentcore-fullstack-webapp) und der AWS-Builders-Artikel "Skip the Middleman: Connecting Your UI Directly to an AI Agent via WebSocket" (https://dev.to/aws-builders/skip-the-middleman-connecting-your-ui-directly-to-an-ai-agent-via-websocket-29f7).

[7] AWS-Bedrock-AgentCore-Developer-Guide. "Configure inbound JWT authorizer": https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/inbound-jwt-authorizer.html

[8] AWS-Bedrock-AgentCore-Developer-Guide. "Authenticate and authorize with Inbound Auth and Outbound Auth": https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-oauth.html

[9] AWS-Bedrock-AgentCore-Developer-Guide. "Get workload access token": https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/get-workload-access-token.html

[10] GitHub, aws/bedrock-agentcore-sdk-python Issue #158: offener AgentCore-Identity-Bug für benutzerdefinierte OAuth2-Provider. https://github.com/aws/bedrock-agentcore-sdk-python/issues/158

[11] Fehlende Skill-Unterstützung für S3 und Git als Quelle. https://github.com/hashicorp/terraform-provider-aws/issues/48540