Project Overview
In this capstone lesson, you will build a complete AI agent that performs four real-world tasks on behalf of an authenticated user: verifying identity through authentication, reading and writing records to a database, calling external APIs to fetch or send data, and enforcing role-based access control (RBAC) so users only see what they are allowed to see. This is the integration point where every previous concept in the course connects.
The agent you build follows a request-response pattern: a user sends a request, the agent checks who the user is, decides what the user is allowed to do, then either queries the database, calls an API, or both, and returns a result. We will use Python for the agent logic, a SQL database for persistence, a mock external API for external data, and a simple JWT (JSON Web Token) mechanism for authentication.
Architecture and Setup
Before writing code, let us sketch the four moving parts and how they connect. The user sends a request with a JWT token. The agent validates the token, extracts the user ID and role, then routes the request to either a database handler or an API caller depending on the user's intent. The database handler uses parameterized SQL queries to prevent injection attacks. The API caller attaches the same JWT to outbound requests so the external service can independently verify the caller.
This UserContext object travels with every internal call. Once a request enters the agent, the context is stamped on it and every downstream function receives the same context, so authorization checks happen at every step, not only at the entry point.
Implementing Authentication
Authentication means proving who the user is. We will use a simple JWT-style token: a base64-encoded string containing the user ID, role, and an expiry timestamp, signed with a shared secret. In production you would use a library like PyJWT, but here we keep it minimal so you can see the mechanics.
The verify_token function is the gatekeeper. Every protected endpoint calls it first. If the token is tampered, expired, or missing, the request is rejected before any database or API code runs.
Querying the Database Safely
With authentication done, the next step is letting the agent read user records. The critical rule here is: never build SQL by string concatenation. Always use parameterized queries so user input is treated as data, not as executable SQL.
Notice how the user ID is passed as a tuple parameter, not interpolated into the string. This single habit blocks SQL injection, which is the most common database attack.
Calling External APIs
Many agent tasks need data the database does not have, such as shipping status from a courier or weather for a delivery route. The agent calls an external HTTP API, passing the same JWT so the external service can verify the caller.
The token is forwarded, not a new one generated. This lets the courier service log who asked and apply its own rate limits per user.
Enforcing Role-Based Access Control
Authentication tells you who the user is. Authorization (RBAC) tells you what they are allowed to do. The cleanest place to enforce this is a small policy function called at every entry point.
A regular user calling list_all_orders gets rejected. An admin calling it gets the full table. The policy check is one line, but it is the difference between a secure system and a data breach.
Tying It All Together
The main agent function ties authentication, database access, API calls, and RBAC into one flow.
Every path starts with verify_token. Every path that touches sensitive data calls require_role. Every database query is parameterized. Every outbound API call carries the user's token. These four habits, repeated everywhere, are what make the agent production-ready.
Summary
You now have a working end-to-end agent. Authentication proves identity through signed tokens. Parameterized SQL queries read and write data without injection risk. Outbound API calls reuse the same token so external services can audit and rate-limit per user. Role-based access control sits at every entry point, not just the front door, so privilege escalation requires bypassing multiple checks. When you build real agents, the pattern is the same: authenticate once, authorize everywhere, parameterize always, and propagate context through every call.
Lesson Checkpoint
Review what you learned and get feedback on your work.