# Conclusion
Source: https://notes.kodekloud.com/docs/12-Factor-App/Conclusion/Conclusion/page
This article provides insights and examples for building scalable, resilient, and maintainable cloud-native applications using the 12-Factor App methodology.
Congratulations on completing your deep dive into the 12-Factor App methodology!
We trust this article has provided valuable insights and practical examples that empower you to build modern, cloud-native applications. By embracing these principles, you can create applications that are scalable, resilient, and easy to maintain—qualities that are essential in today's dynamic development landscape.
The 12-Factor App is much more than a set of best practices; it is a mindset that supports efficient and sustainable application development.
Whether you're developing a small microservice or a large-scale enterprise solution, implementing these principles will give your project a strong and future-proof foundation.
Thank you for engaging with this material. Keep learning, keep building, and continue to innovate in your future endeavors.
# Introduction
Source: https://notes.kodekloud.com/docs/12-Factor-App/Introduction/Introduction/page
This lesson covers the 12-Factor App methodology for building scalable and manageable cloud-native applications.
Welcome to this lesson on the 12-Factor App methodology—a set of best practices for building scalable, resilient, and manageable cloud-native applications. My name is Mumshad Mannambeth, and I'll be your guide as we explore the core principles essential for modern software development.
In today's software landscape, designing applications that can effortlessly scale and adapt is crucial. The 12-Factor methodology outlines clear guidelines for developers, architects, and DevOps engineers who aim to create high-performance applications in the cloud.
In this lesson, we will delve into each of the 12 factors, explaining the concepts behind them with a narrative approach and demonstrating real-world scenarios to illustrate their importance and implementation.
Whether you're a developer, architect, or DevOps engineer, this lesson is designed to equip you with the essential knowledge and tools to build modern, cloud-native applications.

If you're ready to dive in and explore these principles further, let's get started on building applications that are not only efficient but also future-proof.
# Why 12 Factor app
Source: https://notes.kodekloud.com/docs/12-Factor-App/Introduction/Why-12-Factor-app/page
The article discusses the Twelve-Factor App methodology for building scalable, resilient, and maintainable applications in modern cloud environments.
Imagine having a brilliant idea and building an application to share that vision with the world. In the past, launching an application involved overcoming numerous obstacles such as long waiting periods for a dedicated server. Once acquired, that server was permanently tied to your application, and scaling meant adding more resources to that single machine. Often, session data was stored locally, meaning that if the server failed, user progress was lost, and users had to restart from scratch.
Fast forward to today. High-growth SaaS startups can see user numbers rise from zero to millions in mere months. The speed of innovation now hinges on how quickly you can write, test, and deploy your code. Thanks to modern cloud platforms, provisioning and hosting resources can take minutes—or even seconds. With Platform-as-a-Service (PaaS) and serverless technologies, you simply write your code, push it, and see it live. These platforms boast uptimes of 99.999%, making downtime for maintenance, patching, or scaling nearly unacceptable.
For optimal performance and reliability, your application must be architected to decouple from the underlying infrastructure. This means designing for portability and seamless operation across various environments—be it on-premises, Google Cloud Platform (GCP), Amazon Web Services (AWS), or Microsoft Azure—without necessitating changes to your source code.
In earlier architectures, scaling was achieved by vertically enhancing a server, an approach that often required taking the application offline for upgrades. Modern applications, however, scale horizontally by adding more servers and spinning up additional instances. To succeed in today’s fast-paced cloud environments, your application needs to be consistent across development, testing, and production while remaining easily scalable.
A decade ago, engineers at Heroku distilled a set of guiding principles for building modern applications, known today as the 12-Factor App. These twelve principles provide a blueprint for creating scalable, resilient, and maintainable applications. For additional details, refer to the [12factor.net](https://12factor.net/) website.

# Admin Processes
Source: https://notes.kodekloud.com/docs/12-Factor-App/Twelve-Factor-App-methodology/Admin-Processes/page
This article discusses the importance of isolating administrative tasks from main application processes in the 12-Factor App methodology.
In this lesson, we delve into the final principle of the [12-Factor App](https://learn.kodekloud.com/user/courses/12-factor-app) methodology—admin processes. This principle emphasizes the importance of isolating one-off or periodic administrative tasks from the main application processes to ensure that these tasks run on an identical setup as the production environment.
Currently, our application leverages a Redis database to store the count of total visitors. However, there may be instances where the counter becomes inaccurate or requires a reset. In such cases, it is crucial to execute a one-time administrative task without disrupting the running application.
Administrative tasks—such as resetting visitor counts, executing database migrations, or correcting specific user records—must be performed as isolated, one-off processes. This approach enables automation, scalability, and reproducibility while maintaining a production-like environment.
For example, to reset the visitor count stored in Redis, you can execute an admin script. In our setup, this might involve launching an additional Docker container that connects to the same Redis database and runs the reset script:
```python theme={null}
import os
from redis import Redis
# Establish a connection to the Redis database using environment variables for host and port.
redis_db = Redis(host=os.getenv('HOST'), port=os.getenv('PORT'))
redis_db.set('visitorCount', 0)
```
The code above demonstrates how to connect to the Redis database and reset the `visitorCount` to 0. Running tasks like this as isolated, one-off processes ensures that they are automated, scalable, and reproducible, in alignment with the [12-Factor App](https://learn.kodekloud.com/user/courses/12-factor-app) principle of keeping admin tasks separate from long-running application processes.
The admin processes principle advocates for executing any administrative task—whether it is a one-time operation or a periodic task—in isolation. This guarantees that these operations remain automated, scalable, and reproducible, while mirroring the configuration of the primary application environment.
# Backing Services
Source: https://notes.kodekloud.com/docs/12-Factor-App/Twelve-Factor-App-methodology/Backing-Services/page
Backing services are external resources your application relies on, enabling consistent integration and flexibility across different deployment environments.
Backing services are external resources that your application depends on. These services can range from caching solutions like Redis to email providers, object storage services, and more. For instance, we integrated Redis as a caching service in our application to store the visitor count. Other typical backing services include:
* SMTP services for sending emails
* S3 integrations for storing images
* Managed databases and search engines
Your application should be designed to interact with these backing services as attached resources. This means that regardless of whether the service is hosted locally, on a managed cloud platform, or as a cloud-native service, the integration remains consistent. The application code should remain unchanged when switching between different deployment environments.
The concept of treating backing services as attached resources enables seamless scaling and flexibility. Simply update configuration details to point your application to a new instance without modifying any code logic.
## Redis as a Backing Service Example
Consider Redis, which we use as a caching layer:
* **Local Instance:** You might run Redis on your local machine during development.
* **Cloud Deployment:** In a production environment, Redis might be hosted on a cloud provider like AWS or Azure.
* **Managed Service:** Alternatively, you could use a managed Redis service offered by various vendors.
Despite these variations, your application logic remains the same. You only need to update the connection settings to point to the chosen Redis instance.
Ensure that all your backing services are configurable via environment variables or external configurations. This decouples service specifics from your application code, enhancing portability and maintainability.
## Why This Architecture Matters
By decoupling applications from the specific implementations of backing services, you gain flexibility and resilience in your deployment. Whether scaling up in cloud environments or switching service providers, your application's core functionality remains intact.
For more detailed insights and integration guidelines, explore comprehensive examples and further documentation on working with backing services.
## Additional Resources
* [Kubernetes Basics](https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/)
* [Kubernetes Documentation](https://kubernetes.io/docs/)
* [Docker Hub](https://hub.docker.com/)
* [Terraform Registry](https://registry.terraform.io/)
This approach not only simplifies deployments but also enhances the maintainability of your system by following best practices for service-oriented design.
# Build Release and Run
Source: https://notes.kodekloud.com/docs/12-Factor-App/Twelve-Factor-App-methodology/Build-Release-and-Run/page
This article explores the deployment process phases Build, Release, and Run, emphasizing their separation to minimize downtime and enhance consistency.
In this article, we explore the key phases in our deployment process: Build, Release, and Run. A recent typo in the browser message highlighted the importance of separating these stages. While minor typos can be fixed with a simple commit, using a strict separation between build and run phases minimizes downtime in more complex environments.
For example, here is the corrected version of our Flask application that fixes the typo:
```python theme={null}
import os
from flask import Flask
from redis import Redis
app = Flask(__name__)
redisDb = Redis(host=os.getenv('HOST'), port=os.getenv('PORT'))
@app.route('/')
def welcomeToKodeKloud():
redisDb.incr('visitorCount')
visitCount = str(redisDb.get('visitorCount'), 'utf-8')
return "Welcome to KODEKLOUD! Visitor Count: " + visitCount
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
```
After pushing this commit, visiting the application displays:
```plaintext theme={null}
Welcome to KODEKLOUD! Visitor Count: 9
```
For minor fixes, a direct commit may suffice. However, in complex environments where rapid deployment is critical, separating the build, release, and run phases is essential to maintain uptime.
Adhering to the principles of the [12 Factor App](https://learn.kodekloud.com/user/courses/12-factor-app) methodology, our deployment process strictly separates these stages. The diagram below illustrates the separation between build, release, and run phases:

## Phases of the Deployment Cycle
1. **Build Phase**\
In the build phase, developers write code using their favorite editors (such as VS Code or PyCharm). The source code is then transformed into an executable artifact—like a binary or a Docker image. Our process uses a Dockerfile along with the Docker build command to create the image for our application:
```bash theme={null}
$ docker build -t myapp:latest .
```
2. **Release Phase**\
Once the build is ready, the executable artifact is bundled with environment-specific configuration files to form the release object. Each release is uniquely identifiable (using versions like v1, v2, v3, or even timestamps), ensuring that even a minor change, such as a typo fix, generates a new release. Consider this sample configuration:
| Configuration Variable | Value | Description |
| ---------------------- | ---------------- | ---------------------------- |
| HOST | "redis\_db\_dev" | Hostname of the Redis server |
| PORT | "6379" | Port for connecting to Redis |
```plaintext theme={null}
HOST = "redis_db_dev"
PORT = "6379"
```
3. **Run Phase**\
In the run phase, the same build artifact is deployed across various environments (development, testing, production) to ensure consistency. This uniformity makes it easier to roll back to previous releases or redeploy specific versions when necessary. The final running version of our application remains identical to the artifact built earlier:
```python theme={null}
import os
from flask import Flask
from redis import Redis
app = Flask(__name__)
redisDb = Redis(host=os.getenv('HOST'), port=os.getenv('PORT'))
@app.route('/')
def welcomeToKodeKloud():
redisDb.incr('visitorCount')
visitCount = str(redisDb.get('visitorCount'), 'utf-8')
return "Welcome to KODEKLOUD! Visitor Count: " + visitCount
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
```
Deploy the application using the same Docker build process:
```bash theme={null}
$ docker build -t myapp:latest .
```
With the corresponding configuration:
```plaintext theme={null}
HOST = "redis_db_dev"
PORT = "6379"
```
Ensure that environment configurations are correctly managed during the release phase to avoid deployment issues. Misconfiguration at this stage can lead to unexpected application behavior.
By delineating the build, release, and run phases, we can store build artifacts in a dedicated repository, allowing seamless rollback or redeployment of specific versions. This methodology not only streamlines software management but also significantly enhances deployment consistency and reliability.
For further reading on this methodology, refer to the [12 Factor App documentation](https://learn.kodekloud.com/user/courses/12-factor-app).
# Codebase
Source: https://notes.kodekloud.com/docs/12-Factor-App/Twelve-Factor-App-methodology/Codebase/page
This article explores the 12-Factor App methodology with a simple example using Python and Flask to guide scalable application development.
In this article, we will explore the 12-Factor App methodology while demonstrating a simple example built with Python and the Flask web framework. These principles are designed to guide the development of scalable, resilient, and maintainable applications.
The 12 factors are as follows:
1. Have one codebase.
2. Explicitly declare and isolate dependencies.
3. Store configuration in the environment.
4. Treat backing services as attached resources.
5. Strictly separate build and run stages.
6. Execute the app as one or more stateless processes.
7. Export services via port binding.
8. Scale out via the process model.
9. Maximize robustness with fast startup and graceful shutdown.
10. Keep development, staging, and production as similar as possible.
11. Treat logs as event streams.
12. Run admin or management tasks as one-off processes.
## A Simple Flask Example
We begin with a basic Flask application that displays a simple message when accessed via a browser. The entry point for our Flask app is the `app.py` file, which is responsible for handling all incoming and outgoing requests.
Below is the code for our simple Flask app:
```python theme={null}
from flask import Flask
app = Flask(__name__)
@app.route('/')
def welcomeToKodeKloud():
return "Welcome to KODEKLOUD!"
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
```
When you run this application and navigate to its URL in your browser, the homepage will display the message "Welcome to KODEKLOUD!".
At this stage, the code is stored only on your local machine.
## The First Factor: One Codebase
The first principle of the 12-Factor App methodology insists on maintaining a single codebase per application. This approach is essential as your user base expands and new features are added, especially when multiple developers are involved. Each developer works on their own local environment while committing changes to a central repository.
Without a proper version control system, concurrent modifications by different developers could lead to conflicts. This is where Git becomes invaluable. Git enables concurrent contributions to the same codebase by facilitating operations like pulling the latest changes with the `git pull` command, making local updates, and pushing new commits using `git push`.
The central repository is typically hosted on a cloud platform. For example, [GitHub](https://github.com) is a popular platform for hosting Git repositories, while [GitLab](https://about.gitlab.com) and [Bitbucket](https://bitbucket.org) offer similar solutions.

### Managing Multiple Applications
Consider starting with an initial web application. Over time, you might expand your system by adding services such as order processing or delivery functionalities. In the past, it was common to maintain a single codebase for all related applications. However, once multiple services are deployed, the architecture becomes distributed, and sharing one codebase across multiple applications violates the 12-Factor App principles. Each application should reside in its own codebase.

Within a single codebase, you can still deploy multiple instances of your application across various environments (such as development, staging, and production). This strategy ensures that while each application maintains its isolated codebase, you can manage multiple deployments seamlessly.

This structure not only keeps your development process organized but also promotes consistency across different environments, allowing for smoother transitions between development, testing, and production stages.
## Summary
By following the principles outlined in the 12-Factor App methodology, you ensure that every aspect of your application—from a single codebase to distinct deployments across environments—is optimized for scalability and maintainability. Leveraging tools like Git further enhances collaborative development, helping you manage changes effectively as your application grows.
For more insights on scalable application design and best practices, explore our additional resources and documentation linked below.
* [Flask Documentation](https://flask.palletsprojects.com/)
* [GitHub Guides](https://guides.github.com/)
* [12 Factor App](https://12factor.net)
# Concurrency
Source: https://notes.kodekloud.com/docs/12-Factor-App/Twelve-Factor-App-methodology/Concurrency/page
This article explores concurrency as a key concept in application design, focusing on horizontal scaling and its benefits for handling increased load.
In this lesson, we explore the critical concept of concurrency, which is the eighth factor in the [12 Factor App](https://learn.kodekloud.com/user/courses/12-factor-app) methodology.
Up to now, we have containerized our application and executed it as a Docker container, running a single process capable of serving multiple users concurrently. While this setup works well under moderate demand, it has limitations under increased load.
Scaling strategies come in two flavors: vertical and horizontal. Vertical scaling adds more resources to a single server, but this approach can lead to downtime and has inherent resource limits.
Modern deployment strategies favor horizontal scaling, where additional servers are provisioned rapidly to run multiple instances of the application simultaneously. A load balancer then distributes incoming user requests across these instances, ensuring smooth performance even during peak demand.
For horizontal scaling to be effective, your application must be designed as an independent, stateless service. In line with the [12 Factor App](https://learn.kodekloud.com/user/courses/12-factor-app) principles, processes are treated as first-class citizens. Instead of scaling up a single instance with more resources, the application should scale out by running multiple instances concurrently.
* Avoids the single point of failure inherent in vertical scaling.
* Improves fault tolerance and overall system reliability.
* Facilitates easier deployment and maintenance of application instances.
In the next lesson, we will delve deeper into how these principles impact application processes and discuss practical strategies for designing applications that can scale horizontally.
For more information, explore:
* [Kubernetes Basics](https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/)
* [Kubernetes Documentation](https://kubernetes.io/docs/)
* [Docker Hub](https://hub.docker.com/)
* [Terraform Registry](https://registry.terraform.io/)
# Config
Source: https://notes.kodekloud.com/docs/12-Factor-App/Twelve-Factor-App-methodology/Config/page
This article explores externalizing application configuration to support different environments, enhancing flexibility and security while reducing errors.
In this article, we explore how to externalize your application's configuration to support different environments such as production, staging, and development. In our initial Python example, configuration values like the Redis host and port are hard-coded. This approach leads to issues, as each environment may require distinct settings, making it error-prone and inflexible.
By moving configuration values out of the application code, you can manage settings dynamically and securely across different environments.
## Hard-Coded Configuration: The Problem
Consider the following Python snippet, which uses fixed values for connecting to a Redis instance:
```python theme={null}
from flask import Flask
from redis import Redis
app = Flask(__name__)
redisDb = Redis(host='redis-db', port=6380)
@app.route('/')
def welcomeToKodeKLOUD():
redisDb.incr('visitorCount')
visitCount = str(redisDb.get('visitorCount'), 'utf-8')
return "Welcome to KODEKLOUD! Visitor Count: " + visitCount
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
```
Hard-coding configuration values like the Redis host and port can introduce discrepancies when deploying your application to multiple environments. Each environment might use a different Redis instance, and updating these values in the code increases the risk of running into inconsistencies and deployment errors.
## Using Environment Variables for Configuration
To separate configuration from core application logic and secure sensitive details, store your environment-specific settings in a dedicated file, typically named `.env`. With the ".env" file, Python libraries can automatically load environment variables that can be accessed directly in your code.
This approach aligns with the [12 Factor App](https://learn.kodekloud.com/user/courses/12-factor-app) methodology, which emphasizes storing configuration in the environment. As a result, you can seamlessly transition between testing, staging, and production setups without making changes to the core code.
### Example .env File
Below is an example of how your `.env` file might look:
```env theme={null}
HOST=redis_db
PORT=6379
```
Depending on your deployment environment, the configuration might vary as follows:
* **Development Environment:**
```env theme={null}
HOST=redis_db_dev
PORT=6379
```
* **Staging Environment:**
```env theme={null}
HOST=redis_db_staging
PORT=6379
```
* **Production Environment:**
```env theme={null}
HOST=redis_db_prod
PORT=6379
```
Using environment variables to manage configuration ensures that you can safely open source your project without exposing sensitive details. This setup also facilitates smoother deployments across various environments.
By adopting this method, you reduce the risk of configuration-related errors and enhance the security and scalability of your application. For more insights into environment configuration best practices, visit our [Kubernetes Documentation](https://kubernetes.io/docs/) and [Docker Hub](https://hub.docker.com/).
# Dependencies
Source: https://notes.kodekloud.com/docs/12-Factor-App/Twelve-Factor-App-methodology/Dependencies/page
This article explores declaring and isolating dependencies in the 12-Factor App methodology using Flask and discusses best practices for managing them.
In this article, we explore the second rule of the 12-Factor App methodology: explicitly declaring and isolating dependencies. To illustrate this concept, we use the popular Python web framework, Flask.
Before writing any application code, you must install Flask in your local development environment. For example:
```bash theme={null}
$ pip install flask
```
Below is a simple Flask application (app.py):
```python theme={null}
from flask import Flask
app = Flask(__name__)
@app.route('/')
def welcomeToKodeKloud():
return "Welcome to KODEKLOUD!"
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
```
As your application grows, you may need to integrate additional third-party libraries. The 12-Factor App approach dictates that you must not rely on the implicit presence of system-wide packages. In other words, you cannot assume that dependencies like Flask will already be installed on the system where your application executes. They must be explicitly declared and isolated.
A common Python practice is to list dependencies in a file named `requirements.txt`. This file should include both package names and specific version numbers. For example:
```text theme={null}
flask==2.0.0
```
Specifying version numbers is crucial to ensure consistency across various environments such as development, staging, and production. Installing the dependencies is as simple as running:
```bash theme={null}
$ pip install -r requirements.txt
```
This command ensures that every dependency listed in `requirements.txt`—including the specified version of Flask—is installed uniformly.
When developing multiple applications on a single machine, use isolated environments to avoid dependency conflicts. Virtual environments ensure each application manages its own version of every dependency.
Python's virtual environments solve version conflicts by isolating dependencies for each application. This isolation is imperative when one app requires one version of Flask while another requires a different version.

Combining the use of `requirements.txt` with virtual environments guarantees that your explicit dependency packages are consistent across development, staging, and production.
In some cases, your application might depend on system-level tools (such as the curl command) that fall outside Python’s dependency management. In these instances, leveraging a platform like Docker can be highly effective. Docker containers offer a self-contained environment that ensures all necessary tools and configurations are present.
Below is an example Dockerfile that packages the Flask application along with its dependencies into a Docker container:
```docker theme={null}
FROM python:3.10-alpine
WORKDIR /kodekloud-twelve-factor-app
COPY requirements.txt /kodekloud-twelve-factor-app
RUN pip install -r requirements.txt --no-cache-dir
COPY . /kodekloud-twelve-factor-app
CMD python app.py
```
This Dockerfile accomplishes the following steps:
1. Creates a Docker image based on the Python 3.10 Alpine base image.
2. Sets the working directory to `/kodekloud-twelve-factor-app`.
3. Copies the `requirements.txt` file into the working directory.
4. Installs the dependencies specified in `requirements.txt`, without caching.
5. Copies the remaining application code into the image.
6. Defines the command to run the application.
After building the Docker image with the appropriate Docker build command, you can run your application using the Docker run command.
If you're new to Docker, be sure to check out our free [Docker Training Course for the Absolute Beginner](https://learn.kodekloud.com/user/courses/docker-training-course-for-the-absolute-beginner) on KodeKloud. This interactive course offers hands-on labs and an immersive learning environment where you can practice with real systems and servers.
Happy coding!
# Dev Prod Parity
Source: https://notes.kodekloud.com/docs/12-Factor-App/Twelve-Factor-App-methodology/Dev-Prod-Parity/page
This article discusses the importance of maintaining consistency between development and production environments to streamline deployment and enhance application performance.
In this article, we delve into the importance of maintaining parity between development and production environments. By reducing discrepancies across these stages, teams can streamline their deployment process and ensure consistency in how applications perform across environments.
## Traditional Environment Setup
Most development workflows historically involve three distinct environments:
1. **Development (Dev):**\
Developers build and test new features in this phase. Often, lightweight tools or databases (e.g., SQLite) are used to accelerate iterative development.
2. **Staging:**\
This environment closely mirrors production and is used for final testing and validation, ensuring that new changes behave as expected under realistic conditions.
3. **Production (Prod):**\
The live environment accessed by end users, which typically relies on more robust tools and services (e.g., PostgreSQL) to support real-world usage.
## Challenges in Traditional Workflows
Historically, transitioning code from development to production could span weeks or even months. This separation often led to several issues:
* **Time Gap:**\
Delays between development and production deployment can introduce discrepancies. Features may evolve after initial development, potentially affecting performance in production.
* **Personnel Gap:**\
When separate teams handle development and deployment, operations teams might not be fully aware of the latest changes, complicating troubleshooting.
* **Tools Gap:**\
Using different tools and environments in each stage can result in unexpected issues once changes are deployed.
The 10th principle of the [12 Factor App](https://learn.kodekloud.com/user/courses/12-factor-app) framework emphasizes minimizing differences between development, staging, and production. This approach streamlines continuous integration and delivery pipelines, reducing the inherent gaps in traditional setups.

## Modern Practices for Dev-Prod Parity
Advances in continuous integration (CI) and continuous delivery/deployment (CD) now enable teams to roll out changes in hours—or even minutes. This rapid feedback loop ensures that new changes function correctly and issues are identified early.
Moreover, the adoption of modern containerization platforms like Docker has enhanced the ability to maintain similar environments across all stages. By using the same set of tools from development to production, teams can effectively minimize surprises during deployment.

Maintaining parity across development, staging, and production is crucial for achieving reliable, continuous deployments. By bridging the gaps in time, personnel, and tooling, teams can ensure that new features and updates are deployed smoothly and perform consistently in production.
# Disposability
Source: https://notes.kodekloud.com/docs/12-Factor-App/Twelve-Factor-App-methodology/Disposability/page
This article explores the principle of disposability in application processes, emphasizing quick startups, graceful shutdowns, and their importance for dynamic scaling.
In this lesson, we explore the essential principle of disposability as outlined in the [12 Factor App](https://learn.kodekloud.com/user/courses/12-factor-app) methodology. Disposability means that application processes should be designed to be disposable—they can be started or stopped at a moment's notice. This ability is critical for dynamic scaling, where additional instances can be quickly provisioned as application load increases, and unnecessary processes can be terminated just as rapidly when the load decreases.
Disposability is not just about fast startups; it also emphasizes graceful shutdowns to handle ongoing work seamlessly.
A core aspect of disposability is the process of graceful shutdown. When a process receives a termination signal (SIGTERM) from the process manager, it must not immediately exit but rather conclude its active operations to prevent abrupt disruption. This approach ensures users experience minimal interruption, even when scaling down resources.

## Graceful Shutdown in Docker Containers
A practical example of disposability can be observed in Docker’s handling of container shutdowns. When executing the `docker stop` command, Docker sends a SIGTERM signal to the container to initiate a graceful shutdown. If the container does not respond within a certain grace period, Docker then sends a SIGKILL signal to forcefully terminate the process. This two-step mechanism ensures that the container has ample time to complete processing any active requests before termination.
```bash theme={null}
$ docker stop
```
The graceful shutdown process is especially crucial for applications handling multiple requests concurrently. By allowing the application to finish processing existing requests while stopping further intake, the risk of data loss or resource leaks is minimized.
## Practical Application
For instance, consider a Flask application. It should be engineered to intercept the SIGTERM signal and begin a controlled shutdown process. This design ensures that any ongoing tasks are completed before the application terminates, thereby maintaining service continuity and protecting data integrity.
Ensure your application handles SIGTERM signals properly to prevent abrupt terminations that might lead to data loss or resource leaks. Design your termination routines to complete current transactions before shutting down completely.
# Logs
Source: https://notes.kodekloud.com/docs/12-Factor-App/Twelve-Factor-App-methodology/Logs/page
This article explores the logging mechanism of an application, detailing its importance for monitoring, troubleshooting, and various storage approaches.
In this article, we explore the logging mechanism used by our application and how it handles various output events like server startup, port listening, HTTP requests, and error reporting. Logs are crucial for monitoring system activities and troubleshooting issues.
When the application starts, it produces logs detailing the server startup sequence, including server addresses and port numbers. Every HTTP request served is recorded, as illustrated in the example below.
```Python theme={null}
* Serving Flask app 'main'
* Debug mode: on
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:8080
Press CTRL+C to quit
* Restarting with stat
* Debugger is active!
* Debugger PIN: 547-019-069
127.0.0.1 - - [25/Feb/2023 16:19:24] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [25/Feb/2023 16:19:24] "GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [25/Feb/2023 16:19:26] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [25/Feb/2023 16:19:27] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [25/Feb/2023 16:19:27] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [25/Feb/2023 16:19:27] "GET / HTTP/1.1" 200 -
```
These logs not only capture standard operations of the server but also record errors and other significant events, making them indispensable for diagnosing issues when failures occur.
## Logging Storage Approaches
Traditionally, applications write logs to local files. However, in containerized environments, this method presents challenges:
* **Volatility:** A container may terminate at any time, causing the loss of local log files.
* **Inflexibility:** Tying your logging system to a specific file system location restricts scalability and portability.
An alternative is to send logs to a centralized logging server using systems such as Fluentd, the ELK Stack, or Splunk. While centralized logging enhances management and analysis, directly integrating your application with a specific logging provider is not recommended.
Always design your application so that it remains agnostic to any logging backend, which improves flexibility, scalability, and ease of maintenance.
## Example: Sending Logs via Fluentd
The following Python code demonstrates how logs can be sent to a Fluentd logging server. Note, however, that this pattern directly couples your application to Fluentd, which is discouraged:
```python theme={null}
from fluent import sender
# Configure logger for remote logging via Fluentd
logger = sender.FluentSender('app', host='host', port=24224)
# Emit a log event with details
logger.emit('follow', {'from': 'userA', 'to': 'userB'})
```
According to the 11th principle of the [12 Factor App](https://learn.kodekloud.com/user/courses/12-factor-app) methodology, applications should not be responsible for log storage or routing. Instead, all logs should be directed to standard output or written as structured JSON to a local file. This practice allows an external agent to collect and forward logs to a centralized repository, where they can be queried and analyzed efficiently.
Centralized logging solutions like the ELK Stack and Splunk are designed to ingest and process structured log data, making log analysis faster and more effective.
By decoupling the logging mechanism from your application, you ensure that your system remains agile and well-suited for cloud-native and containerized environments.
# Port Binding
Source: https://notes.kodekloud.com/docs/12-Factor-App/Twelve-Factor-App-methodology/Port-Binding/page
This article explains port-binding in Flask applications, highlighting how to access them and the importance of unique ports in multi-service environments.
Accessing our Flask web application is as straightforward as entering the URL along with the port number into your web browser. In our example, the application runs on port 5000. When accessed successfully, a welcome message along with a visitor count is displayed.

By default, the Python Flask framework listens on port 5000. However, when running multiple instances of the application on the same server, each instance can bind to a unique port (such as 5001, 5002, etc.). In multi-service environments, different services are assigned distinct ports—for instance, Redis typically operates on port 6379.

Binding an application to a specific port allows it to export HTTP as a service and listen directly for incoming requests. In contrast to traditional web applications that depend on an external web server, the 12-Factor App methodology encourages creating self-contained applications with built-in web servers. This design approach not only simplifies deployment but also enhances scalability.
For environments that host multiple services simultaneously, ensuring each service is bound to a unique port is crucial for preventing conflicts and maintaining smooth communication between services.
# Processes
Source: https://notes.kodekloud.com/docs/12-Factor-App/Twelve-Factor-App-methodology/Processes/page
This article explores the design of stateless processes in the 12 Factor App methodology for scaling applications and maintaining consistency.
In this article, we explore the design of stateless processes as defined in the [12 Factor App](https://learn.kodekloud.com/user/courses/12-factor-app) methodology. A stateless process shares nothing, a principle that is critical for scaling applications and maintaining consistency when multiple processes are running concurrently.
Suppose we want to implement a new feature that displays the visitor count on our website. Each time a visitor accesses the page, the application should update and display the total visit count. Initially, we modify our code to include a global variable that tracks the number of visits, incrementing it with every incoming request:
```python theme={null}
from flask import Flask
app = Flask(__name__)
visitCount = 0
@app.route('/')
def welcomeToKodeKloud():
global visitCount
visitCount += 1
return "Welcome to KODEKLOUD! Visitor Count: " + str(visitCount)
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
```
This solution works perfectly when running a single process because the visit count is stored within that process's memory. However, when multiple instances are deployed, each process maintains its own independent version of the variable. Consequently, visitors might see different counts depending on which process handles their request.
A similar challenge arises with session-specific data. For instance, when a user logs in, session details (like user location and session expiration) are stored in the server's memory. If subsequent requests are routed to a different process, the session information may be missing and the user might be inadvertently logged out.
Even though load balancers can use session-aware mechanisms (sticky sessions) to direct a user to the same process, this approach is unreliable. In case of a process failure, any locally stored data is lost.

This scenario emphasizes a core principle of the 12-Factor methodology: processes must be stateless and share nothing. Relying on sticky sessions contradicts this principle. Instead, all state information should be stored in external backing services, allowing all processes to access uniform data regardless of which instance handles a given request.

A typical solution is to use an external service, such as a database or caching system like [Redis](https://redis.io), for persistent state or session data. To implement this approach, we modify our application so that the visit count is maintained in a Redis database rather than in the process's memory:
```python theme={null}
from flask import Flask
from redis import Redis
app = Flask(__name__)
redisDb = Redis(host='redis-db', port=6380)
@app.route('/')
def welcomeToKodeKloud():
redisDb.incr('visitorCount')
visitCount = str(redisDb.get('visitorCount'), 'utf-8')
return "Welcome to KODEKLOUD! Visitor Count: " + visitCount
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
```
With this updated implementation, the application scales seamlessly. Multiple instances can operate concurrently, all accessing the same consistent state through the centralized Redis database. This design adheres to the 12-Factor principle of statelessness and ensures your application remains robust and scalable in dynamic environments.
# Deploying Azure AI Services
Source: https://notes.kodekloud.com/docs/AI-102-Microsoft-Certified-Azure-AI-Engineer-Associate/Get-Started-with-Azure-AI-Services/Deploying-Azure-AI-Services/page
Guide for provisioning and configuring Azure AI Services, selecting resource types, managing endpoints and keys, planning deployments, and connecting applications via REST APIs or language SDKs
This guide shows how to provision and configure Azure AI Services, choose the appropriate resource type, and connect from applications using REST APIs or language SDKs. It covers portal setup, deployment considerations, authentication, and sample requests so you can get a tested endpoint, keys, and region for development or production.
## Create an Azure AI resource
To get started, create an Azure AI resource in the Azure portal. Required information includes:
* Subscription and resource group
* Deployment region — pick a region close to your users to reduce latency and meet data residency requirements
* Instance name
* Pricing tier — some capabilities may offer a free tier for experimentation; otherwise select a plan matching your expected usage
After entering the required fields, click Review + Create to provision the resource.
Tip: Use a descriptive name and consistent tagging for resources to simplify billing, monitoring, and automation. Free tiers are ideal for testing but verify quotas and limits before using in production.
## Multi-service vs Single-service resources
When creating a resource you can choose between:
* Multi-service resource: exposes multiple AI capabilities (Language, Vision, Speech, etc.) through a single endpoint and shared keys — simplifies management and billing.
* Single-service resource: scoped to one capability (for example, a Language-only or Vision-only resource) with its own endpoint and keys — useful for isolation, fine-grained permissions, or separate team ownership.
Use the table below to decide which fits your scenario.
| Resource Type | When to use | Benefits |
| -------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| Multi-service | Small teams or consolidated billing; want a single endpoint for multiple AI capabilities | Fewer endpoints/keys, simplified management |
| Single-service | Separate teams, strict access control, or different regions/tiers per capability | Isolation, granular permissions, independent lifecycle |
Choose single-service resources when you need strict separation (for example, the Vision team should not access Speech). Choose multi-service to simplify management and reduce the number of endpoints and keys.
## Deployment considerations
Plan these factors before provisioning to avoid rework:
* Subscription & region — compliance, data residency, and latency constraints
* Pricing & tiers — costs, quotas, and available features differ by tier
* Security & access — use Azure RBAC, key rotation, and managed identities where possible
### Endpoints, keys, and locations
After deployment you will obtain:
* Endpoint — base URL your application calls
* Keys — typically two API keys for key rotation; either key can be used
* Location — region hosting the resource (for example, eastus). Some SDKs and REST endpoints require the region value
Example values (format):
```text theme={null}
https://ai102-cog.cognitiveservices.azure.com/
eastus
```
| Artifact | Description |
| -------: | --------------------------------------------------------------- |
| Endpoint | Base URL for REST and SDK calls |
| Keys | API keys for authentication (rotate regularly) |
| Location | Azure region of the resource; used for some requests or routing |
Best practice: rotate keys regularly and prefer Microsoft Entra ID (OAuth bearer tokens) where supported for stronger identity-based authentication. See Microsoft Entra ID docs: [https://learn.microsoft.com/en-us/azure/active-directory/](https://learn.microsoft.com/en-us/azure/active-directory/)
## Accessing Azure AI Services via REST APIs
REST endpoints provide platform-independent access to Azure AI capabilities. Typical request flow:
1. Client sends an HTTP request to the service endpoint.
2. Request contains authentication (API key header or Microsoft Entra ID bearer token).
3. Request body is JSON following the service schema.
4. Service returns a structured JSON response with analysis results.
Authentication options:
| Method | Header example | When to use |
| -------------------------- | -------------------------------------- | -------------------------------------------------------------------------- |
| API key | `api-key: ` | Simple setup, suitable for server-to-server calls or quick testing |
| Microsoft Entra ID (OAuth) | `Authorization: Bearer ` | Preferred for production deployments; supports RBAC and managed identities |
Example curl request (replace placeholders):
```bash theme={null}
curl -X POST "https:///language/analyze?api-version=2024-01-31" \
-H "Content-Type: application/json" \
-H "api-key: " \
-d '{
"kind": "SentimentAnalysis",
"analysisInput": {
"documents": [
{ "id": "1", "language": "en", "text": "I love the new product!" }
]
},
"parameters": {}
}'
```
Example JSON response structure:
```json theme={null}
{
"results": {
"documents": [
{
"id": "1",
"sentiment": "positive",
"confidenceScores": {
"positive": 0.99,
"neutral": 0.01,
"negative": 0.0
}
}
],
"errors": []
}
}
```
REST usage benefits:
* Full control over HTTP behavior and payloads
* Platform/language agnostic
* Useful for environments without official SDK support
## Using SDKs
Official SDKs reduce boilerplate and provide language-native interfaces, automatic retries, and credential handling. SDKs are available for .NET, Python, Node.js, and Java.
Benefits of SDKs:
* Simplified authentication and request construction
* Native response objects and error types
* Built-in retry logic and telemetry integration
Example Python (Text Analytics) using the azure-ai-textanalytics SDK:
```python theme={null}
from azure.ai.textanalytics import TextAnalyticsClient
from azure.core.credentials import AzureKeyCredential
endpoint = "https:///"
key = ""
client = TextAnalyticsClient(endpoint=endpoint, credential=AzureKeyCredential(key))
documents = ["I had a wonderful day!"]
response = client.analyze_sentiment(documents)
for doc in response:
print(f"Document sentiment: {doc.sentiment}")
print(f"Confidence scores: {doc.confidence_scores}")
```
SDKs are wrappers around REST APIs and are recommended for most development scenarios unless you need direct control of raw HTTP requests.
## Summary and next steps
You now know how to:
* Provision an Azure AI resource in the portal
* Choose between multi-service and single-service resources
* Plan deployment with region, pricing, and security in mind
* Retrieve endpoint, keys, and location values
* Call services via REST or use language SDKs for faster integration
Next step: Provision an AI resource in your Azure subscription, record the endpoint, keys, and region, and run the curl or SDK examples above from a development environment.
## Links and references
* [Microsoft Entra ID (Azure AD) documentation](https://learn.microsoft.com/en-us/azure/active-directory/)
* [Azure AI documentation](https://learn.microsoft.com/azure/ai-services)
* [Azure SDKs and tools](https://learn.microsoft.com/azure/developer/python/)
# Module Introduction
Source: https://notes.kodekloud.com/docs/AI-102-Microsoft-Certified-Azure-AI-Engineer-Associate/Get-Started-with-Azure-AI-Services/Module-Introduction/page
Intro to Azure AI Services showing how to call prebuilt language, speech, vision, and generative models via REST APIs and SDKs and integrate them into cloud applications.
Getting started with Azure AI Services
This lesson introduces Azure AI Services and shows how to use them from both REST APIs and SDKs. By the end of the module you’ll be able to discover available services, call pre-built models programmatically, and integrate AI capabilities into cloud applications.
What you’ll learn
* The types of AI services available in Azure — language, speech, vision, and generative AI — and the scenarios where they apply.
* How to call Azure AI Services using REST APIs as well as client libraries (for example, Python and C#) so you can use pre-built models without training your own.
* How to wire these services into real-world cloud apps (chatbots, image analysis pipelines, recommendation systems) and deploy them in the cloud.
Learning objectives
| Objective | Outcome | Example |
| ------------------------------------: | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| Understand Azure AI service offerings | Know which service fits a given scenario (language understanding, speech, vision, generative) | Choose Speech-to-Text for transcribing calls; use Computer Vision to tag images |
| Use REST APIs and SDKs | Call models from code or scripts using HTTP or client libraries (Python, C#) | Send a text prompt to a generative model via REST or the Python SDK |
| Integrate services into cloud apps | Design and deploy workflows that combine AI capabilities with other Azure services | Build a chatbot using Language Service, host it in Azure App Service, store logs in Cosmos DB |
How this lesson is organized
* Overview of Azure AI Services and common scenarios (language, speech, vision, and generative AI).
* Demonstrations of calling services:
* REST API patterns (authentication, endpoints, request/response shapes).
* Client SDK usage (Python and C# examples with recommended libraries).
* Integration and architecture patterns:
* Combining multiple services in pipelines.
* Reliable production patterns (retries, batching, monitoring).
* Deployment considerations:
* Secure keys and managed identities.
* Scaling and cost control.
Before you begin: make sure you have an Azure subscription and access to the relevant AI service resources (or an admin who can provision them). Install the Azure CLI and the SDK for your language of choice (Python or .NET) to follow the hands‑on examples.
Why this matters (SEO keywords)
* Azure AI Services provide pre-trained models and managed APIs for adding intelligence to applications quickly.
* Using REST APIs and SDKs reduces time-to-integration so teams can focus on product features rather than model training.
* Integration patterns help you build scalable, maintainable cloud solutions that combine speech, vision, language, and generative capabilities.
Links and references
* [Azure AI Services overview](https://learn.microsoft.com/azure/ai-services/)
* [Azure Cognitive Services documentation](https://learn.microsoft.com/azure/cognitive-services/)
* [Azure SDKs for Python](https://learn.microsoft.com/azure/developer/python/) and [.NET](https://learn.microsoft.com/dotnet/azure/)
Throughout the lesson we’ll walk through key concepts, concise examples of calling services, and practical patterns for integrating AI into cloud-based solutions. Let’s dive in and start adding intelligence to your applications.
# Working with Azure AI Services
Source: https://notes.kodekloud.com/docs/AI-102-Microsoft-Certified-Azure-AI-Engineer-Associate/Get-Started-with-Azure-AI-Services/Working-with-Azure-AI-Services/page
Guide to creating Azure AI Language services and performing sentiment analysis using Python SDK and REST API, comparing approaches and covering endpoints, keys, security, and best practices.
This guide demonstrates how to create an Azure AI Language service in the Azure portal and call its sentiment analysis capability using both the Python SDK and the REST API. You’ll see that the SDK provides a more concise developer experience, while the REST example shows the underlying HTTP payloads and is useful when SDKs are unavailable.
What you'll learn:
* How to create an Azure AI service (multi-service account vs. single dedicated service)
* Where to find endpoints and keys
* Example code for sentiment analysis using the Python SDK
* Example code for sentiment analysis using the REST API
* When to choose SDK vs. REST
## Create an Azure AI service in the portal
If you already have a multi-service account, it exposes multiple capabilities (OpenAI, Speech, Vision, Language, etc.) under the same account-level keys. The portal lists AI service resources like this:
If you open a multi-service account and look at Keys and Endpoint, you'll see the shared account-level keys and multiple capability endpoints (OpenAI, Speech, Content Safety, Computer Vision, Content Understanding, etc.).
If you prefer a single-purpose resource (for example, a dedicated Language resource), create it from the Language service blade. During creation:
* Select a subscription and resource group (e.g., rg-ai102-get-started-sdk)
* Choose a region (e.g., East US)
* Provide a globally unique resource name (this becomes \.cognitiveservices.azure.com)
* Pick a pricing tier (for example S1)
Create the resource and then check the resource group/overview to confirm creation.
Once created, open the resource and go to **Keys and Endpoint** to copy the endpoint URL and one of the two keys for use in your client code.
Do NOT embed long-lived keys directly in source code for production. Use Azure Key Vault, managed identities, or environment variables to secure secrets.
## Choose: SDK vs REST
Both approaches return a sentiment label and confidence scores. Use SDKs when available for a cleaner, idiomatic interface and automatic authentication helpers. Use REST when SDKs are not available or you need direct HTTP access.
Comparison at a glance:
| Resource | Use case | Pros |
| ----------------------------------- | ------------------------------------------------- | ---------------------------------------------------------- |
| Python SDK (azure-ai-textanalytics) | Typical development on Python | Concise code, structured objects, handles auth and retries |
| REST API (HTTP POST) | Direct HTTP integrations, non-supported languages | Shows exact payload and headers, no SDK dependency |
Useful links:
* [Azure AI Language service overview](https://learn.microsoft.com/azure/ai-services/)
* [Azure SDK for Python - Text Analytics docs](https://learn.microsoft.com/azure/cognitive-services/text-analytics/overview)
* [Language REST API reference (analyze-text)](https://learn.microsoft.com/azure/cognitive-services/language-service/rest-api)
## SDK approach (Python)
Install the SDK packages:
pip install azure-core azure-ai-textanalytics
Example Python SDK usage. Replace endpoint and key with your values (do not hard-code in production).
```python theme={null}
# python
import os
from azure.core.credentials import AzureKeyCredential
from azure.ai.textanalytics import TextAnalyticsClient
def authenticate_client(endpoint: str, key: str) -> TextAnalyticsClient:
"""
Authenticate and return a TextAnalyticsClient using the provided endpoint and key.
"""
credential = AzureKeyCredential(key)
client = TextAnalyticsClient(endpoint=endpoint, credential=credential)
return client
def sentiment_analysis(client: TextAnalyticsClient, text: str):
"""
Perform sentiment analysis on a single document string.
"""
try:
response = client.analyze_sentiment([text])[0]
print(f"\nDocument Sentiment: {response.sentiment}")
print(
f"Overall scores: positive={response.confidence_scores.positive:.2f}, "
f"neutral={response.confidence_scores.neutral:.2f}, "
f"negative={response.confidence_scores.negative:.2f}"
)
return response
except Exception as err:
print(f"Encountered exception: {err}")
return None
def main():
# Replace with your endpoint and key (do not hard-code in production)
endpoint = "https://ai102cogservices909.cognitiveservices.azure.com/"
key = ""
sample_text = "Learning AI is good for career growth."
client = authenticate_client(endpoint, key)
print("Performing sentiment analysis:")
sentiment_result = sentiment_analysis(client, sample_text)
if __name__ == "__main__":
main()
```
What the SDK returns:
* Document-level sentiment (positive / neutral / negative)
* Confidence scores for each class
* Optional per-sentence sentiment and additional metadata if requested
## REST approach (Python + requests)
The REST approach requires building the analyze-text URL and POSTing a JSON body. Ensure boolean values in the JSON are proper booleans (true / false), not strings. Use the endpoint that you copied from Keys and Endpoint. The endpoint should usually end with a trailing slash (or adjust URL concatenation accordingly).
Example Python REST code:
```python theme={null}
# python
import requests
import json
def sentiment_analysis(endpoint: str, key: str, text: str):
"""
Call the Azure Language analyze-text REST API for sentiment analysis.
The endpoint should include the trailing slash, e.g. "https://.cognitiveservices.azure.com/".
"""
url = f"{endpoint}language/:analyze-text?api-version=2023-04-15-preview"
headers = {
"Ocp-Apim-Subscription-Key": key,
"Content-Type": "application/json"
}
body = {
"kind": "SentimentAnalysis",
"parameters": {
"modelVersion": "latest",
"opinionMining": True
},
"analysisInput": {
"documents": [
{
"id": "1",
"language": "en",
"text": text
}
]
}
}
try:
response = requests.post(url, headers=headers, json=body)
if response.status_code == 200:
sentiment_data = response.json()
document = sentiment_data["results"]["documents"][0]
print(f"\nDocument Sentiment: {document['sentiment']}")
scores = document["confidenceScores"]
print(
f"Overall scores: positive={scores['positive']:.2f}, "
f"neutral={scores['neutral']:.2f}, "
f"negative={scores['negative']:.2f}"
)
return document
else:
print(f"Error: {response.status_code}")
print(response.text)
return None
except Exception as err:
print(f"Encountered exception: {err}")
return None
def main():
endpoint = "https://ai102cogservices909.cognitiveservices.azure.com/" # Endpoint URL (include trailing slash)
key = ""
sample_text = "The food and service were unacceptable."
print("Performing sentiment analysis:")
sentiment_analysis(endpoint, key, sample_text)
if __name__ == "__main__":
main()
```
Notes on the REST example:
* The REST payload reveals the exact request structure (kind, parameters, analysisInput.documents).
* Set "opinionMining": true to enable opinion mining in results; omit or set false if not needed.
* The header shown uses Ocp-Apim-Subscription-Key; depending on your resource type, you may also see header variants (follow the current Azure REST docs).
## Comparing results and examples
Both SDK and REST return a sentiment label and confidence scores. Example inputs and typical outcomes:
* "Learning AI is good for career growth." — typically returns positive with a high positive confidence score.
* "The food and service were unacceptable." — typically returns negative.
* Mixed content — e.g., "Hotel is awesome. The food and service were unacceptable." — shows how per-sentence analysis can reveal mixed sentiments inside a single document.
Use per-sentence results when you need more granular insights about different parts of a document.
## Best practices & next steps
* For production, never hard-code credentials. Use:
* Azure Key Vault
* Managed identities (when running in Azure)
* Environment variables with secure deployment pipelines
* Prefer SDKs for simpler, cleaner code and better integration with client libraries.
* Use REST for custom clients, language/platforms without an SDK, or to inspect raw payloads.
Always restrict and rotate keys regularly. Grant the minimum required permissions and monitor usage for unexpected calls.
You can apply the same patterns shown here to other Azure AI services (Vision, Speech, OpenAI, Content Safety). In later examples we'll use a mix of SDKs and other languages (for example, C#/.NET) where applicable.
# Azure AI Search
Source: https://notes.kodekloud.com/docs/AI-102-Microsoft-Certified-Azure-AI-Engineer-Associate/Introduction-to-AI-and-Azure-AI-Services/Azure-AI-Search/page
Overview of Azure AI Search, an AI-powered service that enriches, indexes, and semantically ranks documents using OCR, NLP, embeddings, and knowledge mining for improved enterprise search
Azure AI Search (formerly Azure Cognitive Search) is an AI-powered search and knowledge-mining service that helps users find the most relevant information across large, heterogeneous data collections. It combines document cracking, AI enrichment, indexing, semantic ranking, and querying to turn raw documents into actionable, searchable knowledge.
Key SEO terms: Azure AI Search, Azure Cognitive Search, AI enrichment, semantic ranking, vector search, knowledge mining, indexing, OCR, entity recognition.
## What Azure AI Search does — at a glance
* AI-powered indexing: Automatically extracts and structures searchable fields from documents, databases, and file stores.
* Natural-language understanding: Uses NLP to interpret user intent and return conceptually relevant results beyond exact keyword matches.
* Semantic ranking: Prioritizes results that are most relevant by understanding relationships between words and concepts.
* Knowledge mining: Extracts entities, key phrases, and relationships from structured and unstructured sources (PDFs, images, spreadsheets, etc.) for downstream use.
| Capability | What it does | Typical use case |
| ----------------------: | --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| AI-powered indexing | Enriches content (OCR, entity extraction, key phrases) and converts it into searchable fields | Indexing large sets of PDFs or scanned documents for enterprise search |
| Natural-language search | Interprets intent and matches concepts rather than exact keywords | Conversational search queries like “top-selling product in Q1” |
| Semantic ranking | Ranks results using embeddings/semantic models to surface most helpful answers | Improving relevance for question-answering or knowledge base lookups |
| Knowledge mining | Detects entities and builds relationships across documents | Building knowledge graphs or metadata layers for BI and analytics |
## How Azure AI Search works — the pipeline
Azure AI Search usually follows a simple pipeline: ingestion → AI enrichment → indexing → querying. Each stage transforms your raw data into structured, searchable knowledge.
1. Raw data sources
* Files, blobs, databases, or other storage systems.
2. AI enrichment pipeline
* Applies cognitive skills such as OCR (for scanned images), entity recognition, key-phrase extraction, language detection, translation, and custom skills to extract structured content from unstructured documents.
3. Indexing
* Converts enriched content into a searchable index: text fields, filters, facets, scoring profiles, and optionally vector embeddings for semantic or vector search.
4. Querying and ranking
* Applications and users query the index using text queries, filters, facets, or semantic queries. Results are ranked by relevance, scoring profiles, and semantic ranking when enabled.
| Pipeline stage | Primary function | Output |
| -------------- | --------------------------------------------------- | ------------------------------------- |
| Ingestion | Bring raw files and data into the pipeline | Documents/blobs/records |
| AI enrichment | Extract structured fields and metadata from content | Enriched documents (JSON) |
| Indexing | Create searchable index and optional vectors | Search index with fields & embeddings |
| Querying | Execute queries and return ranked results | Ranked search results & facets |
If terms like "indexing", "AI enrichment", or "skillset" are unfamiliar, think of them this way: indexing is how documents are organized for fast search; enrichment is the AI work that extracts searchable metadata; a skillset is the collection of enrichment steps (OCR, entity extraction, custom code).
## Core concepts explained
* Index: A data structure that Azure Search uses to enable fast search operations (fields, data types, analyzers).
* Skillset: A pipeline of cognitive skills that transform raw content into enriched JSON fields.
* Cognitive skills: Prebuilt (OCR, language detection) or custom functions that extract entities, key phrases, or apply business logic.
* Semantic configurations: Settings that enable semantic ranking and passage retrieval using embeddings or language models.
* Vector/semantic search: Uses vector embeddings to find conceptually similar content, especially useful for natural language queries and question-answering.
## Example: Minimal REST search request
Below is a simplified example of a search POST request to an Azure Search index (semantic search preview API). Replace placeholders with your service name, index name, and API key.
```http theme={null}
POST https://.search.windows.net/indexes//docs/search?api-version=2021-04-30-Preview
api-key:
Content-Type: application/json
{
"search": "top-selling product in Q1",
"queryType": "semantic",
"semantic": {
"configuration": "default"
},
"top": 5
}
```
Use the latest API version for production and consult Azure docs for semantic features and vector search options:
* [https://learn.microsoft.com/azure/search/](https://learn.microsoft.com/azure/search/)
## When to use Azure AI Search
* Enterprise search portals across documents and knowledge bases.
* Customer support knowledge bases, to power FAQ and conversational interfaces.
* Content discovery for digital asset management (images, video transcripts, PDFs).
* Building knowledge graphs and downstream analytics from mined entities.
## Quick-start checklist
* Create an Azure AI Search service in the Azure portal.
* Define an index schema for fields and data types.
* Create a skillset for AI enrichments (OCR, named-entity recognition, key phrases).
* Run indexer to ingest and enrich documents.
* Configure semantic settings or vector search for better relevance.
* Integrate via REST SDKs or client libraries and tune scoring profiles.
## Links and references
* [Azure AI Search documentation](https://learn.microsoft.com/azure/search/)
* [Azure Cognitive Services overview](https://learn.microsoft.com/azure/cognitive-services/)
* [Semantic search with Azure Cognitive Search](https://learn.microsoft.com/azure/search/semantic-search-overview)
We have completed the introduction to Azure AI Services. Upcoming lessons will cover how to deploy these services, configure indexes and skillsets, and make REST API calls to interact with the search service.
Next up: hands-on configuration — creating a search service, defining an index, and applying AI enrichments to real data.
# Azure AI Services
Source: https://notes.kodekloud.com/docs/AI-102-Microsoft-Certified-Azure-AI-Engineer-Associate/Introduction-to-AI-and-Azure-AI-Services/Azure-AI-Services/page
Overview of Azure AI Services and how to integrate language, speech, vision, and generative AI capabilities into applications with minimal code and managed APIs
In this lesson we explore Azure AI Services — a set of managed, production-ready AI capabilities you can integrate into applications to add intelligence without training models from scratch. Azure groups these offerings by capability so you can pick the best service for your scenario, whether you need language understanding, speech, vision, or generative AI.
These services speed up development and reduce operational overhead: with a few API calls or a small SDK integration you can add document reading, speech transcription, image understanding, or generative content to your app.
## Capabilities overview
Below is a concise breakdown of the primary capability areas and what they enable:
### Language (Azure AI Language Services)
* Text analysis: extract language, key phrases, entities, and structured information from text.
* Sentiment analysis: classify text as positive, negative, or neutral.
* Translation: convert text between languages in real time.
* QnA / knowledge mining: build question-answering systems from documents and knowledge bases.
### Speech (Azure Speech services / Speech SDK)
* Speech-to-text (recognition): convert spoken audio into transcribed text.
* Text-to-speech (synthesis): generate natural-sounding audio from text.
* Speech translation: translate spoken language in real time and produce synthesized output.
### Vision (Azure AI Vision / Document Intelligence)
* Image & video processing: analyze frames to detect scenes, faces, activities, and visual insights.
* Image classification: label images with objects, scenes, or tags.
* Object detection: locate and label objects with bounding boxes.
* OCR (optical character recognition): extract text from scanned documents and images.
### Generative AI (Azure OpenAI and related services)
* Text generation: create human-like text for emails, summarization, code, or creative writing.
* Image generation: create or transform images from text prompts.
* Assistants & custom conversational experiences: build chat-based or multi-modal assistants powered by large generative models.
Azure packages these capabilities into focused offerings such as:
* Azure AI Language Services
* Azure AI Vision
* Azure AI Document Intelligence
* Azure AI Search
* Azure OpenAI Resource
With minimal SDK setup or a few REST API calls, you can add document reading, speech transcription and translation, image understanding, and generative content directly into your applications.
## Service map: which Azure resource to choose
| Service / Resource | Primary use case | Quick example |
| ------------------------------ | ------------------------------------------------------- | ------------------------------------------ |
| Azure AI Language Services | Text analytics, entity extraction, translation, QnA | Sentiment analysis, key phrase extraction |
| Azure Speech | Speech-to-text, text-to-speech, speech translation | Live transcription and TTS for apps |
| Azure AI Vision | Image and video analysis | Object detection, image classification |
| Azure AI Document Intelligence | Document parsing, OCR, structured data extraction | Invoice parsing, form understanding |
| Azure AI Search | Indexing and semantic search over documents | Search experience with AI-enriched results |
| Azure OpenAI Resource | Generative text and image models, conversational agents | Summaries, code generation, assistants |
## Quick-start examples
Text analytics (sentiment) — REST (curl)
```bash theme={null}
curl -X POST "https://.cognitiveservices.azure.com/text/analytics/v3.1/sentiment" \
-H "Ocp-Apim-Subscription-Key: " \
-H "Content-Type: application/json" \
-d '{
"documents": [
{ "id": "1", "language": "en", "text": "Azure AI Services make development faster!" }
]
}'
```
Speech recognition — JavaScript (Speech SDK)
```javascript theme={null}
import { SpeechConfig, AudioConfig, SpeechRecognizer } from "microsoft-cognitiveservices-speech-sdk";
const speechConfig = SpeechConfig.fromSubscription("", "");
const audioConfig = AudioConfig.fromDefaultMicrophoneInput();
const recognizer = new SpeechRecognizer(speechConfig, audioConfig);
recognizer.recognizeOnceAsync(result => {
console.log("Recognized text:", result.text);
recognizer.close();
});
```
These snippets demonstrate how little code is required to start adding AI to your application.
Tip: Start with managed services (Language, Speech, Vision) for common scenarios. Use Azure OpenAI for advanced generative tasks and custom assistants. Combine services—for example, use OCR from Document Intelligence + Azure AI Search for semantic search over scanned documents.
Warning: When integrating AI features, protect sensitive data and ensure compliance with regional data residency and privacy requirements. Review Azure’s data processing terms and choose the right resource type and region for your workload.
## Next steps and resources
* Azure AI Services overview: [https://learn.microsoft.com/azure/ai-services](https://learn.microsoft.com/azure/ai-services)
* Azure AI Language documentation: [https://learn.microsoft.com/azure/ai-services/language/](https://learn.microsoft.com/azure/ai-services/language/)
* Azure Speech documentation: [https://learn.microsoft.com/azure/cognitive-services/speech-service/](https://learn.microsoft.com/azure/cognitive-services/speech-service/)
* Azure AI Vision & Document Intelligence: [https://learn.microsoft.com/azure/ai-services/vision/](https://learn.microsoft.com/azure/ai-services/vision/)
* Azure OpenAI documentation: [https://learn.microsoft.com/azure/cognitive-services/openai/](https://learn.microsoft.com/azure/cognitive-services/openai/)
Detailed coverage of these services — including integration patterns, SDK samples, and best practices for production deployments — is available in the linked docs.
# Azure Machine Learning
Source: https://notes.kodekloud.com/docs/AI-102-Microsoft-Certified-Azure-AI-Engineer-Associate/Introduction-to-AI-and-Azure-AI-Services/Azure-Machine-Learning/page
Overview of Azure Machine Learning, Microsoft's cloud service for building, training, deploying, and managing machine learning models with MLOps, experiment tracking, and scalable compute.
Azure Machine Learning (Azure ML) helps organizations turn data into actionable insights by enabling teams to build, train, register, and deploy machine learning models at scale. Before we define the service, consider a practical scenario where AI creates measurable impact.
Imagine a hospital handling hundreds of patients daily. Clinicians must make fast, high-stakes decisions often with limited information. Traditional diagnosis relies on observable symptoms and clinician experience, which can miss subtle signals, confuse diseases with similar presentations, or overlook rare conditions.
Machine learning augments clinical judgment by combining diverse medical data—patient records, reported symptoms, lab results, imaging, and other diagnostics—so models can learn complex patterns not visible from a single data source. This enables earlier detection of conditions such as diabetes, cardiovascular risk, or cancer, resulting in faster, more accurate care and improved patient outcomes.
## What is Azure Machine Learning?
Azure Machine Learning is Microsoft’s cloud service designed for data scientists and developers to manage the end-to-end machine learning lifecycle. It provides managed compute, scalable storage, experiment tracking, model registries, and deployment endpoints—so teams can focus on building models and delivering predictions rather than operating infrastructure.
Key capabilities include:
* Managed compute: interactive compute instances, training clusters, and inference targets.
* Experimentation and reproducibility: tracking runs, logs, and metrics.
* Model registry and versioning: store and manage production-ready models.
* Flexible deployment: real-time (online) endpoints and batch scoring pipelines.
* Integrations: AutoML, Azure ML Studio, Python SDK, and Azure CLI.
* MLOps support: CI/CD, repeatable pipelines, and governance for production ML.
## Simplified Azure ML workflow
Below is a streamlined view of the typical Azure ML lifecycle—useful for planning ML projects, regulatory compliance, and operationalizing models.
| Step | Purpose | Example / Artifact |
| ----------------------------- | ----------------------------------------------- | ----------------------------------------------- |
| Data collection & preparation | Ingest and clean datasets; create feature sets | Datasets, Feature stores |
| Compute provisioning | Allocate resources for development and training | Compute instances, compute clusters |
| Experimentation & training | Run training jobs and hyperparameter tuning | Training runs, metrics, logs |
| Model registration | Version and store production-ready models | Model registry entries |
| Deployment | Expose models as endpoints for predictions | Real-time endpoints, batch jobs |
| Consumption & monitoring | Applications query models; monitor performance | Telemetry, drift detection, retraining triggers |
A typical lifecycle maps to Azure ML services (Datasets, Jobs/Experiments, Model Registry, Endpoints) and integrates with CI/CD for production deployments.
## Integrations and best practices
Azure ML supports the full lifecycle: data preparation (Datasets), training (Jobs/Experiments), orchestration and CI/CD for models (MLOps), model registry, and deployments (real-time and batch). It also integrates with AutoML for common tasks and provides SDKs and studio interfaces for reproducible workflows.
For production-grade ML, consider:
* Automating training and deployment with pipelines and CI/CD.
* Monitoring model performance and data drift to trigger retraining.
* Using model explainability tools to increase transparency.
* Enforcing role-based access and audit trails for governance.
When working with healthcare or sensitive data, ensure compliance with regulations such as HIPAA and GDPR. Use Azure security features—private networks (VNet), role-based access control (RBAC), encryption at rest and in transit, and audit logging—to protect patient information.
## Links and references
* Azure Machine Learning documentation: [https://learn.microsoft.com/azure/machine-learning/](https://learn.microsoft.com/azure/machine-learning/)
* Azure AI services overview: [https://learn.microsoft.com/azure/ai-services/](https://learn.microsoft.com/azure/ai-services/)
* Fundamentals of MLOps course: [https://learn.kodekloud.com/user/courses/fundamentals-of-mlops](https://learn.kodekloud.com/user/courses/fundamentals-of-mlops)
* HIPAA overview: [https://www.hhs.gov/hipaa/index.html](https://www.hhs.gov/hipaa/index.html)
* GDPR overview: [https://gdpr.eu/](https://gdpr.eu/)
This high-level introduction outlines what Azure ML provides and how it fits into real-world workflows. The rest of this article will dive deeper into each core component and practical patterns for production ML.
# Module Introduction
Source: https://notes.kodekloud.com/docs/AI-102-Microsoft-Certified-Azure-AI-Engineer-Associate/Introduction-to-AI-and-Azure-AI-Services/Module-Introduction/page
Overview of AI fundamentals, distinctions between AI, machine learning, and data science, and how Azure AI services and tools support building, deploying, and monitoring intelligent solutions.
Welcome to the first module: Introduction to AI and Azure AI Services.
In this lesson you will:
* Build a clear understanding of the fundamentals of artificial intelligence (AI).
* Learn how AI relates to — and differs from — related fields such as machine learning (ML) and data science.
* Explore the AI capabilities and services available in Microsoft Azure, and how they help you build, train, and deploy intelligent solutions without starting from scratch.
Why this matters
* Precise terminology and a clear mental model help you choose the right tools and design patterns for real-world systems.
* Understanding the boundaries between AI, ML, and data science reduces rework and speeds up solution delivery—from data ingestion and feature engineering to model training, inference, and monitoring.
At a high level:
* AI is the broad discipline of creating systems that perform tasks typically requiring human intelligence (perception, reasoning, language, and planning).
* Machine learning is a subset of AI focusing on algorithms that learn patterns and make predictions from data.
* Data science centers on collecting, preparing, analyzing, and visualizing data to extract insight and support ML model development.
Azure provides a comprehensive set of managed services and tools that accelerate building intelligent solutions. Key capabilities include:
* Pre-built cognitive APIs for vision, speech, language, and decision-making (Azure Cognitive Services).
* End-to-end platforms for training, tracking, and managing models (Azure Machine Learning).
* Model hosting and scalable inference options (managed endpoints, containers, and serverless deployments).
* DevOps and MLOps features to operationalize models: continuous training, monitoring, and governance.
How these areas map to common tasks
| Concept | Primary role | Azure services / tools |
| -------------------------------- | --------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| Data collection & preparation | Ingest, clean, and transform raw data for analysis and training | Azure Data Factory, Azure Databricks, Azure Storage |
| Feature engineering & analysis | Explore data, create features, validate assumptions | Azure Machine Learning, Jupyter notebooks, Databricks |
| Model training & experimentation | Train models, tune hyperparameters, track experiments | Azure Machine Learning, Automated ML |
| Pre-built AI capabilities | Add vision, speech, language, or decision features without building models from scratch | Azure Cognitive Services (Computer Vision, Speech, Language) |
| Model deployment & inference | Host models for real-time or batch predictions | Azure Machine Learning endpoints, AKS, Azure Functions |
| Monitoring & governance | Track performance, drift, and compliance in production | Azure Monitor, Application Insights, Azure ML model monitoring |
What you’ll gain from this module
* A strong conceptual foundation: know when to use pre-built services vs. custom ML models.
* Practical guidance for mapping solution requirements to Azure services.
* An understanding of the typical lifecycle: data → model → deployment → monitoring.
Tip: As you progress, focus on the role each area (AI, ML, data science) plays in a solution — from data collection and model training to deployment and monitoring — so you can choose the right Azure services for each stage.
Links and references
* Microsoft Azure AI documentation: [https://learn.microsoft.com/azure/ai-services](https://learn.microsoft.com/azure/ai-services)
* Azure Machine Learning overview: [https://learn.microsoft.com/azure/machine-learning/](https://learn.microsoft.com/azure/machine-learning/)
* Azure Cognitive Services overview: [https://learn.microsoft.com/azure/cognitive-services/](https://learn.microsoft.com/azure/cognitive-services/)
* Introduction to data science: [https://en.wikipedia.org/wiki/Data\_science](https://en.wikipedia.org/wiki/Data_science)
Recommended next steps
* Review the Azure Cognitive Services and Azure Machine Learning docs for quick-start guides.
* Practice by choosing a small dataset and prototyping a model with Azure Machine Learning or using a Cognitive Service API for inference.
# Responsible AI Considerations
Source: https://notes.kodekloud.com/docs/AI-102-Microsoft-Certified-Azure-AI-Engineer-Associate/Introduction-to-AI-and-Azure-AI-Services/Responsible-AI-Considerations/page
Guidelines for designing, deploying, and governing AI systems to ensure fairness, safety, privacy, inclusiveness, transparency, and accountability throughout the lifecycle.
To harness AI effectively and ethically, teams must design, build, and operate systems that reflect responsible-AI principles. These principles reduce harm, build trust, and improve long-term value by addressing fairness, safety, privacy, inclusiveness, transparency, and accountability from design through deployment and monitoring.
This article outlines six core responsible-AI areas and provides practical examples and mitigation strategies you can apply across projects and organizations.
Six core responsible-AI areas at a glance:
| Principle | Why it matters | Example |
| -------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| Fairness | Prevents AI from amplifying historical or dataset bias and ensures equitable outcomes. | A hiring model that systematically favors male applicants over equally qualified female candidates. |
| Reliability & Safety | Ensures consistent, safe behavior, especially in high-risk systems. | Self-driving car perception failing in low light or adverse weather. |
| Privacy & Security | Protects personal data and defends models and pipelines from attacks or leakage. | Voice assistant recording conversations without consent or model exfiltration via API misuse. |
| Inclusiveness | Makes AI accessible and useful to people with diverse backgrounds, languages, and abilities. | Speech recognition that fails for certain accents or for people with speech impairments. |
| Transparency | Helps users and stakeholders understand how decisions are made and what limitations exist. | Clear reason-giving when a loan application is denied, plus guidance on appeals. |
| Accountability | Assigns ownership for system behavior, incident response, and ongoing improvement. | An organization being responsible for a chatbot giving unsafe medical advice, with governance and audits in place. |
Below are each of the six areas with concise definitions, common risks, and practical mitigations you can adopt.
* Fairness
* What it means: AI should treat all individuals equitably and avoid amplifying historical or dataset biases.
* Common risks: Underrepresentation of groups in training data; biased features; proxy variables that encode sensitive attributes.
* Practical mitigations:
* Curate balanced, representative datasets and document collection processes.
* Audit model outputs across demographic slices and measure disparate impact.
* Apply fairness-aware methods during training (e.g., reweighting, adversarial debiasing) or post-processing adjustments.
* Maintain model cards and data sheets describing limitations and intended use.
* Example: A hiring algorithm favoring male applicants over equally qualified female candidates indicates biased training data or features. Remediate by balancing the dataset, removing proxies for gender, and testing outcomes per group.
* Reliability and Safety
* What it means: AI should perform predictably and avoid causing harm across expected and edge-case conditions.
* Common risks: Model brittleness under distribution shift, sensor failure in physical systems, or unsafe behavior when encountering novel inputs.
* Practical mitigations:
* Test models across diverse and adversarial conditions, including synthetic edge cases.
* Implement redundancy (ensemble models, sensor fusion) and fail-safe mechanisms.
* Use monitoring and alerting in production to detect drift, degradation, or anomalous outputs.
* Define safety requirements and run scenario-based validation for high-risk applications.
* Example: For self-driving cars, perception models must reliably detect stop signs, pedestrians, and hazards even in rain and low light. Mitigations include extensive scenario testing, redundant perception pipelines, and conservative failover policies.
High-risk systems (healthcare, transportation, finance) require additional governance, compliance, and independent safety assessments before deployment.
* Privacy and Security
* What it means: Protect user data and prevent model misuse, data leakage, or unauthorized access.
* Common risks: Unintended data retention, model inversion attacks, weak access controls, or insecure deployment pipelines.
* Practical mitigations:
* Apply data minimization and anonymization techniques; retain only what is necessary.
* Use encryption at rest and in transit, and secure key management.
* Employ differential privacy, federated learning where appropriate, and rate-limiting to resist extraction attacks.
* Enforce role-based access control, audit trails, and secure model hosting practices.
* Example: A voice assistant that records private conversations without consent breaches privacy. Mitigations include explicit consent flows, local processing where feasible, and strict retention policies.
* Inclusiveness
* What it means: Build AI that serves and empowers people from diverse backgrounds, languages, and abilities.
* Common risks: Design choices or datasets exclude certain groups; interfaces that are inaccessible.
* Practical mitigations:
* Collect representative data across languages, accents, age groups, and abilities.
* Involve diverse user groups in testing and usability studies, including people with disabilities.
* Design accessible interfaces (keyboard navigation, screen-reader compatibility, clear language).
* Provide multilingual support and localization of content.
* Example: Speech-recognition apps that work poorly for certain accents exclude many potential users. Mitigate by expanding accent-varied datasets and continuous user testing.
* Transparency
* What it means: Provide clear, appropriate explanations about how AI decisions are made, including limitations and intended use.
* Common risks: Opaque models that users cannot interrogate, missing documentation, or misleading system behavior.
* Practical mitigations:
* Publish model cards, data sheets, and clear user-facing disclosures about capabilities and limitations.
* Implement decision explanations tailored to context (e.g., feature importance for an auditor, plain-language reasons for a user).
* Log inputs and outputs to support post hoc analysis and audits.
* Make model evaluation metrics, datasets, and testing procedures available to stakeholders where feasible.
* Example: If an AI denies a loan, the applicant should receive clear, actionable reasons (e.g., low income or insufficient credit history) and instructions for appeal.
* Accountability
* What it means: Define clear ownership for the AI system’s behavior, operation, and improvement, backed by governance and incident response.
* Common risks: Diffused responsibility across teams, lack of incident logs, or absence of remediation plans.
* Practical mitigations:
* Assign a responsible person or team for AI governance, monitoring, and incident response.
* Maintain auditable logs, version control for models and data, and documented SOPs for incidents.
* Conduct regular audits, risk assessments, and post-deployment reviews.
* Establish escalation paths and remediation workflows for harmful outputs.
* Example: If a chatbot provides harmful medical advice, the deploying organization—not just the developer—must be accountable for monitoring, updating, and remediating the system. Establish accountability through governance structures, incident response plans, logging, and regular audits.
Iterate, measure, and improve
* Apply these principles from project inception: bake responsible-AI checks into requirements, design reviews, data collection, and model evaluation.
* Monitor continuously in production for drift, fairness regressions, and emergent risks.
* Update models and processes as new issues are discovered; treat responsible AI as an ongoing program, not a one-time checklist.
Further reading and resources
* [Kubernetes Documentation](https://kubernetes.io/docs/) (operational best practices for AI platforms)
* [NIST AI Risk Management Framework](https://www.nist.gov/itl/ai-risk-management-framework)
* [Microsoft Responsible AI resources](https://learn.microsoft.com/responsible-ai)
* [EU AI Act overview](https://digital-strategy.ec.europa.eu/en/policies/regulatory-framework-ai)
This overview summarizes key responsible-AI areas to guide teams toward safer, fairer, and more trustworthy AI systems. Apply the practices above iteratively: design with principles in mind, test thoroughly, monitor continuously, and be prepared to adapt as new risks emerge.
# What Is Artificial Intelligence
Source: https://notes.kodekloud.com/docs/AI-102-Microsoft-Certified-Azure-AI-Engineer-Associate/Introduction-to-AI-and-Azure-AI-Services/What-Is-Artificial-Intelligence/page
Overview of artificial intelligence concepts, applications, developer skills, and responsible governance for building and deploying AI-powered systems.
Artificial intelligence (AI) is the practice of building software that mimics, augments, or automates human capabilities. Historically tasks like translating a sentence required a human translator—an approach that could be slow or expensive for rare languages or urgent needs. Modern AI systems automate translation, speech recognition, image text extraction, and many other tasks quickly and at scale.
Everyday AI examples:
* [Google Translate](https://translate.google.com) — translate pasted text, spoken words, or text captured from images.
* [Microsoft Copilot](https://www.microsoft.com/en-us/microsoft-365/copilot) — helps write emails, summarize documents, and generate Excel formulas from plain-English instructions.
* [GitHub Copilot](https://github.com/features/copilot) — suggests code while developers type.
* [ChatGPT](https://chat.openai.com/) — generates ideas, drafts content, and explains complex topics.
* [Google Lens](https://lens.google/) — recognizes objects and extracts or translates text from images.
AI powers these capabilities by combining models, data, and software interfaces so applications can perform tasks that previously required human judgment or effort.
AI enables faster, more accessible communication and automation—reducing manual effort for translation, transcription, image understanding, and conversational assistance.
## Core AI capability areas
AI systems typically focus on one or more capability areas. The table below summarizes common capability categories, their purpose, and example uses.
| Capability | What it does | Real-world examples |
| --------------------------: | ------------------------------------------------------ | ------------------------------------------------------ |
| Visual perception | Detects and interprets visual information | Object detection, OCR (text in images), face detection |
| Text analysis | Processes and understands written language | Summarization, translation, sentiment analysis |
| Conversation (NLP) | Engages through natural language | Virtual assistants, chatbots, conversational search |
| Decision making & analytics | Makes recommendations or automated decisions from data | Recommender systems, anomaly detection, forecasting |
Note: some applications combine multiple capabilities (for example, an app that recognizes a product from an image and then answers user questions about it).
Some inferences—such as attempting to read emotions from facial expressions—are unreliable and ethically contentious. Design AI systems with care to avoid harm, bias, or false confidence.
## Skills software engineers need to work with AI
Working with AI in production requires both software engineering practices and conceptual understanding of models. Below is a practical breakdown you can use to evaluate or plan skill development.
| Skill category | Key details | Why it matters |
| ------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| Programming & integration | Python, C#, JavaScript; using REST APIs and SDKs to call models and services | Enables building applications that call hosted models or embed ML components |
| DevOps & production engineering | Version control (Git), CI/CD, automated testing, monitoring | Ensures reliable deployments and observability for AI-enabled features |
| Model lifecycle | Training, evaluating, deploying, updating models (even with prebuilt models) | Manages model quality and adapts to data drift or new requirements |
| Model interpretation | Understanding probability scores, confidence, and failure modes | Helps users trust outputs and supports responsible decision-making |
| Responsible AI practices | Fairness, transparency, privacy, and governance | Reduces risk of bias, legal exposure, and user harm |
For example, practical learning paths cover how to start from a base model, deploy it, integrate it with an application via APIs or SDKs, and manage it in production. These are hands-on skills you’ll use to integrate AI responsibly into real systems.
## Responsible AI & governance
Responsible AI is a cross-cutting requirement for production systems. Consider fairness, transparency, privacy, and accountability from design through deployment:
* Evaluate datasets for bias and representativeness.
* Expose confidence and limitations of model outputs to users.
* Log model decisions and monitor performance in production.
* Apply privacy-preserving techniques when handling sensitive data.
Always test AI systems for failure modes and biased behavior before deployment. Ethical reviews and governance policies should be part of your release checklist.
## Links and references
* [Google Translate](https://translate.google.com) — translation and image text recognition
* [Microsoft Copilot](https://www.microsoft.com/en-us/microsoft-365/copilot) — productivity assistant
* [GitHub Copilot](https://github.com/features/copilot) — code completion and suggestions
* [ChatGPT](https://chat.openai.com/) — conversational AI and content generation
* [Google Lens](https://lens.google/) — image recognition and text extraction
These resources and concepts give you a foundation for understanding what AI is, how it’s applied in real products, and the practical skills required to build and govern AI-enabled systems.
# Certification Details
Source: https://notes.kodekloud.com/docs/AI-102-Microsoft-Certified-Azure-AI-Engineer-Associate/Introduction/Certification-Details/page
Concise guide to AI-102 Azure AI Engineer certification, exam domains, required skills, and course resources with labs, mock exams, and study guidance to prepare for the test
Welcome to the AI-102 Certification Details module — your practical roadmap for understanding the exam and how this course prepares you to pass. This lesson outlines the exam structure, highlights the main skill domains you need to master, and shows how to prepare using course resources, mock exams, and official Microsoft materials.
The AI-102 exam evaluates your ability to design and implement AI-powered applications using Microsoft Azure AI Services. Below is a concise, SEO-friendly breakdown of the exam domains and the real-world skills each domain maps to.
High-level overview (by percent of exam)
| Exam Domain | Percentage | Focus / Real-world outcome |
| --------------------------------------------- | ---------: | ----------------------------------------------------------------------------------------- |
| Plan and manage AI solutions | 20–25% | Architecture, governance, cost, and operational planning for Azure AI solutions |
| Develop computer vision solutions | 10–15% | Image and video analysis, face detection, and custom object-detection models |
| Develop natural language processing solutions | 15–20% | Text analytics, question answering, conversational AI, and speech |
| Develop generative AI solutions | 15–20% | Azure OpenAI, prompt engineering, RAG, and integrating generative models |
| Implement knowledge mining solutions | 15–20% | Azure Cognitive Search, Document Intelligence, enrichment pipelines, and knowledge stores |
Below we expand each area with focused takeaways so you know what to study and which hands‑on skills to practice.
Plan and manage AI solutions (20–25%)
* Understand core AI concepts and how Azure AI Services map to solution requirements.
* Choose the right Azure AI components (Vision, Language, Speech, OpenAI, Cognitive Search) and integrate them with enterprise-grade security, monitoring, and cost controls.
* Apply governance and lifecycle practices: authentication (managed identities), role-based access, logging, and responsible AI considerations.
Develop computer vision solutions (10–15%)
* Use prebuilt vision APIs for image analysis, OCR, and face detection.
* Extract searchable metadata from video content and generate frame-level insights.
* Train and evaluate custom models (Azure Custom Vision) to detect domain-specific objects and visual patterns.
* Optimize deployment options for latency and cost (edge vs cloud).
Develop natural language processing solutions (15–20%)
* Perform text analytics: sentiment analysis, key-phrase extraction, language detection, and topic modeling.
* Build question-answering systems and retrieval-backed conversational layers.
* Implement translation and multilingual pipelines with high accuracy.
* Create conversational language understanding solutions: intent recognition, entity extraction, and dialog management.
* Use Document Intelligence to extract structure from documents; implement custom classification and NER for domain-specific labeling.
* Work with speech technologies: speech-to-text, translation, and text-to-speech.
Develop generative AI solutions (15–20%)
* Connect to Azure OpenAI Service to integrate large language models (LLMs) into applications.
* Use SDKs and REST APIs to call models for text generation, summarization, and code generation.
* Improve factuality and relevance using retrieval-augmented generation (RAG) to ground outputs in your documents and databases.
* Apply prompt engineering best practices to design prompts that produce consistent, safe, and useful responses.
Implement knowledge mining solutions (15–20%)
* Build search and indexing solutions with Azure Cognitive Search to surface insights from unstructured data.
* Use Document Intelligence (formerly Form Recognizer) to extract structured fields from invoices, forms, receipts, and contracts.
* Extend enrichment pipelines with Custom Skills for specialized processing.
* Persist enriched, structured data into a Knowledge Store for analytics and queryable outputs.
How this course helps you succeed
* Module-level recap questions reinforce core concepts and check practical knowledge.
* Mock exams simulate the certification environment and highlight knowledge gaps to prioritize study.
* Hands-on labs demonstrate integrations with the Azure SDKs (Python and C#), REST APIs, and Azure Portal workflows.
* Direct links to official Microsoft resources let you review exam objectives and practice with vendor-provided materials.
Before scheduling the exam: ensure you have practical experience with at least one programming language (Python or C#). Most labs and real-world tasks require writing code to call Azure SDKs, manage resources, and integrate services.
Where to find official Microsoft resources
* Official exam page: [AI-102 exam details — Microsoft Learn](https://learn.microsoft.com/en-us/certifications/exams/ai-102/)
* Certification learning path: [Azure AI Engineer — Microsoft Learn](https://learn.microsoft.com/en-us/certifications/azure-ai-engineer/)
* Practice assessments and scheduling: check the official exam page for links to practice tests and Pearson VUE scheduling.
To schedule the exam: sign in with your Microsoft account, select a testing provider (for example, Pearson VUE), and choose a date and time that fits your preparation timeline. Consider taking a practice assessment first to benchmark readiness.
Next steps
Now that you have a clear view of the AI-102 exam structure and the practical skills required, we'll begin a deep dive into planning and managing Azure AI solutions — starting with solution architecture, governance controls, and authentication patterns.
# Course Introduction
Source: https://notes.kodekloud.com/docs/AI-102-Microsoft-Certified-Azure-AI-Engineer-Associate/Introduction/Course-Introduction/page
Introductory course preparing learners for Microsoft Azure AI Engineer Associate certification, teaching Azure AI services, hands-on labs, governance, and exam-focused guidance.
Welcome to the Microsoft Certified Azure AI Engineer Associate (AI-102) course. This program is designed to build practical skills you can apply immediately—whether you're preparing for the certification exam or implementing AI solutions in production.
Azure is a dominant enterprise cloud platform, and its AI services power many real-world applications across industries. Below is a quick snapshot to set the stage.
Azure AI is used for customer support automation, real-time language translation, medical diagnostics, and more. Microsoft reports thousands of organizations relying on Azure AI for data analysis, model deployment, and delivering real-time business value—making this an ideal time to grow your Azure AI skills.
I'm Hrithin Skaria, your instructor for this course. Over the lessons you’ll get a balance of conceptual guidance, hands-on demos, and exam-style questions to build competence and confidence.
What you’ll learn first: core AI concepts and the Azure AI ecosystem. That foundation helps you choose the right services, design suitable architectures, and reason about trade-offs for real projects and exam scenarios.
Next, we’ll cover core service areas in the sequence most engineers use them:
* Computer vision with Azure AI Vision — image and video analysis, object detection, OCR, and face recognition.
* Natural language processing — sentiment analysis, entity recognition, translation, and building conversational bots.
* Generative AI with Azure OpenAI — large language models for summarization, content generation, and advanced conversational experiences.
* Provisioning, security, endpoint management, cost control, and governance for Azure AI resources.
* Knowledge mining with Azure AI Search — indexing documents and extracting structured data to make information searchable and actionable.
* Automation with Azure AI Document Intelligence — extracting structured fields from forms and automating document-based workflows.
You’ll also learn how to provision and manage Azure AI resources, secure models and endpoints, and apply best practices for cost control and governance.
Next: knowledge mining with Azure AI Search—techniques to index and query documents, images, and databases so insights are discoverable and actionable.
Then we’ll cover automation with Document Intelligence to extract structured information from forms, speed up processing, and reduce human error in workflows.
Throughout the course you’ll get hands-on labs, architecture guidance, and exam-focused tips. Participate in community forums to ask questions, collaborate on projects, and learn with peers—community learning speeds progress and keeps you motivated.
Study tip: Combine hands-on labs with the mock exams and architecture walkthroughs. Practical experience with Azure OpenAI, Cognitive Services, and Azure ML will improve your recall for exam scenarios and real-world deployments.
Course modules at a glance
| Module | Key Focus | Example Use Cases |
| ------------------------------------ | --------------------------------------------- | ------------------------------------------------------ |
| AI Fundamentals & Azure AI Ecosystem | Core concepts, service selection | Choosing between Azure ML vs. OpenAI for model hosting |
| Azure Machine Learning | Model training & deployment | MLOps pipelines, model versioning |
| Azure AI Vision & Face Service | Image/video analysis, OCR, facial recognition | Retail inventory analysis, security monitoring |
| Natural Language Processing | Text analytics, NLU, bots | Sentiment analysis, intent recognition |
| Azure OpenAI (Generative AI) | LLM-based generation & chat | Summarization, document Q\&A, assistants |
| Provisioning & Governance | Resource management, security, cost control | Secure endpoints, RBAC, quotas |
| Azure AI Search (Knowledge Mining) | Indexing and search pipelines | Enterprise document search, eDiscovery |
| Document Intelligence | Automated document parsing | Invoice processing, form extraction |
Links and references
* Microsoft Azure AI documentation: [https://docs.microsoft.com/azure/ai-services](https://docs.microsoft.com/azure/ai-services)
* Azure Machine Learning docs: [https://docs.microsoft.com/azure/machine-learning/](https://docs.microsoft.com/azure/machine-learning/)
* Azure Cognitive Services overview: [https://docs.microsoft.com/azure/cognitive-services/](https://docs.microsoft.com/azure/cognitive-services/)
* Azure OpenAI Service: [https://learn.microsoft.com/azure/cognitive-services/openai/](https://learn.microsoft.com/azure/cognitive-services/openai/)
* Azure Cognitive Search: [https://learn.microsoft.com/azure/search/](https://learn.microsoft.com/azure/search/)
Are you ready to unlock the full potential of AI with Azure and take the next step in your career? Let’s begin this journey together and start transforming how you build intelligent solutions.
# Containerizing Azure AI Services
Source: https://notes.kodekloud.com/docs/AI-102-Microsoft-Certified-Azure-AI-Engineer-Associate/Using-Azure-AI-Services-for-Enterprise-Applications/Containerizing-Azure-AI-Services/page
Guide to deploying and running Azure AI services in containers, covering deployment options, data control, scaling, and a hands-on Text Analytics Sentiment container example
Containerizing Azure AI services gives organizations greater flexibility and control over where and how AI workloads run. This guide walks through deployment options, data control, and scaling considerations when running Azure AI in containers — with a hands-on example using the Text Analytics / Sentiment container.
* Deployment options: Run containers locally (developer laptop or edge), in Azure Container Instances (ACI), on Azure Kubernetes Service (AKS), or on other container platforms and clouds.
* Data control: Applications send data to the container for local processing. The container reports only usage telemetry to Azure for billing/licensing; customer data remains on-premises.
* Scalability and flexibility: Run models on-premises, in the cloud, or as a hybrid. Standard orchestration tools like Kubernetes (AKS, EKS) enable scaling and high availability.
## Key deployment options
| Deployment type | Use case | Example |
| ---------------------------------- | ----------------------------------------------------------------------- | -------------------------------------- |
| Local / Edge | Development, testing, or on-device inference | Docker Desktop on a dev machine |
| ACI / Single-node cloud containers | Lightweight cloud hosting without orchestration | Azure Container Instances (ACI) |
| Kubernetes (AKS, EKS, GKE) | Production-grade scaling, rolling updates, and multi-node orchestration | AKS with Horizontal Pod Autoscaler |
| Other clouds / on-prem | Hybrid or multi-cloud deployments | EKS/GKE or private Kubernetes clusters |
## Architecture overview
Typical flow when running Azure AI in containers:
* Pull an AI container image from Microsoft Container Registry (MCR).
* Deploy the image to a container host (local Docker, ACI, AKS, another cloud, etc.).
* Client applications send requests (e.g., text for sentiment analysis) to the container's local REST API.
* The container processes inputs locally and returns responses to the client.
* Periodically, the container emits telemetry (usage metrics) to Azure for billing and licensing — it does not send customer data.
## Running a container locally (example)
For a simple demo, run a Cognitive Services container on Docker Desktop. In production, you would typically use AKS, ACI, EKS, or another orchestrator. This section shows the local workflow for the Text Analytics (Sentiment) container.
1. Find the container image and instructions in Microsoft Docs. See the Language service containers overview and the Sentiment container page:
* [https://learn.microsoft.com/azure/ai-services/language/language-service-containers-overview](https://learn.microsoft.com/azure/ai-services/language/language-service-containers-overview)
2. The MCR image name for sentiment looks like:
```text theme={null}
mcr.microsoft.com/azure-cognitive-services/textanalytics/sentiment
```
Pull the image from MCR:
```bash theme={null}
docker pull mcr.microsoft.com/azure-cognitive-services/textanalytics/sentiment:latest
```
Sample trimmed output (success):
```bash theme={null}
latest: Pulling from azure-cognitive-services/textanalytics/sentiment
...
Digest: sha256:2588b79b18513da0917ff6cc53ef6d8292985d8b1bf83d4f98739f08bb94207f
Status: Downloaded newer image for mcr.microsoft.com/azure-cognitive-services/textanalytics/sentiment:latest
```
If you're using Apple Silicon (ARM) and the container image targets x86\_64 (AMD64), the image may pull successfully but fail to run. Either use an x86\_64 host, an emulator layer (e.g., Docker Desktop Rosetta/QEMU), or check the container docs for a supported ARM build.
## Run the container
The docs include an example docker run command. Replace placeholders with your values:
* — e.g., latest
* — your Cognitive Services endpoint (used for billing/licensing)
* — your Cognitive Services API key
Example command:
```bash theme={null}
docker run --rm -it -p 5000:5000 --memory 8g --cpus 1 \
mcr.microsoft.com/azure-cognitive-services/textanalytics/sentiment:latest \
Eula=accept \
Billing="https://.cognitiveservices.azure.com/" \
ApiKey=""
```
Flags and environment variables explained:
* \--rm: remove the container after exit
* -it: interactive terminal so logs are visible
* -p 5000:5000: map container port 5000 to host port 5000
* \--memory / --cpus: resource limits for the container
* Eula=accept: acknowledge license terms
* Billing: the Cognitive Services endpoint URL for licensing/usage reporting
* ApiKey: your service key for authentication to the container
After the container starts, it listens on localhost:5000. Inspect logs to verify successful startup and that the service is serving requests.
Check running containers:
```bash theme={null}
docker ps
```
## Accessing the API and built-in documentation
Open [http://localhost:5000](http://localhost:5000) in your browser. The container exposes Swagger/Redoc API documentation and health endpoints. Typical endpoints include:
* /authentication/renew — renew tokens used by the container
* /records/usage-logs// — retrieve usage reporting logs
* /sentiment (prediction endpoint)
* /swagger/v3/swagger.json and Swagger UI pages for interactive testing
* /health or other status endpoints
## Sentiment API example
The Sentiment container uses the same REST shape as the cloud Text Analytics API. Send a JSON body with documents and receive sentiment classifications with confidence scores.
Example request body:
```json theme={null}
{
"documents": [
{ "id": "1", "text": "I love this product!" },
{ "id": "2", "text": "This is the worst experience." }
],
"modelVersion": "latest"
}
```
Example response (trimmed):
```json theme={null}
{
"documents": [
{
"id": "1",
"sentiment": "positive",
"confidenceScores": { "positive": 0.99, "neutral": 0.01, "negative": 0.0 },
"sentences": [ /* ... */ ],
"warnings": []
},
{
"id": "2",
"sentiment": "negative",
"confidenceScores": { "positive": 0.0, "neutral": 0.02, "negative": 0.98 },
"sentences": [ /* ... */ ],
"warnings": []
}
],
"modelVersion": "latest"
}
```
## Container status and health
Use the container's status and health endpoints to confirm:
* The API key is valid
* Telemetry/usage reporting is functioning
* Service processes are healthy
A typical status payload might look like:
```json theme={null}
{"service":"sentimentonnx","apiStatus":"Valid","apiStatusMessage":"Api Key is valid, no action needed."}
```
## Summary
Workflow recap:
1. Obtain the MCR image for the desired Azure AI container.
2. Pull and run the container on a host (local Docker, ACI, AKS, etc.).
3. Configure the container with your Billing endpoint and ApiKey.
4. Call the local REST endpoints for inference; the container emits only usage telemetry to Azure for billing/licensing.
## Links and references
* Azure Language service containers docs: [https://learn.microsoft.com/azure/ai-services/language/language-service-containers-overview](https://learn.microsoft.com/azure/ai-services/language/language-service-containers-overview)
* Azure Cognitive Services containers overview: [https://learn.microsoft.com/azure/cognitive-services/](https://learn.microsoft.com/azure/cognitive-services/)
* Kubernetes documentation: [https://kubernetes.io/docs/](https://kubernetes.io/docs/)
# Module Introduction
Source: https://notes.kodekloud.com/docs/AI-102-Microsoft-Certified-Azure-AI-Engineer-Associate/Using-Azure-AI-Services-for-Enterprise-Applications/Module-Introduction/page
Guide to operating Azure AI services in production by securing access, monitoring performance and costs, and deploying containerized models for reliable, scalable enterprise and edge environments.
Welcome to the next lesson: using [Azure AI Services](https://learn.kodekloud.com/user/courses/ai-102-microsoft-certified-azure-ai-engineer-associate) for enterprise applications.
This module shifts focus from building and integrating AI capabilities to operating them reliably at scale. You’ll learn practical operational skills to secure, monitor, and deploy Azure AI Services so your solutions run securely, perform well, and remain cost‑efficient in production environments.
You will cover three core areas that matter for production-grade AI:
1. Authenticate and secure AI services
* Manage API keys and secrets safely
* Store secrets centrally with [Azure Key Vault](https://learn.microsoft.com/azure/key-vault/general/overview)
* Use [Azure Active Directory](https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-whatis) and managed identities to enforce least‑privilege access
* Implement role‑based access control (RBAC) and network isolation via [private endpoints](https://learn.microsoft.com/azure/private-link/private-endpoint-overview) and [VNETs](https://learn.microsoft.com/azure/virtual-network/virtual-networks-overview)
2. Monitor and optimize AI usage
* Track metrics and usage to understand cost and performance drivers
* Collect logs and traces with [Azure Monitor](https://learn.microsoft.com/azure/azure-monitor/overview), [Log Analytics](https://learn.microsoft.com/azure/azure-monitor/logs/log-analytics-overview), and [Application Insights](https://learn.microsoft.com/azure/azure-monitor/app/app-insights-overview)
* Analyze latency, error rates, and throughput to guide autoscaling and cost optimization
3. Deploy AI services in containers
* Containerize models and inference components using Docker best practices
* Run containers locally, in [Azure Container Instances (ACI)](https://learn.microsoft.com/azure/container-instances/container-instances-overview), or on [Azure Kubernetes Service (AKS)](https://learn.microsoft.com/azure/aks/intro-kubernetes)
* Use [Azure Container Registry (ACR)](https://learn.microsoft.com/azure/container-registry/container-registry-intro) or private registries for controlled image distribution
* Plan for edge deployments and air‑gapped or private‑network scenarios where public endpoints are not available
Why this matters: securing access, instrumenting services early, and using containers for predictable deployments are essential to running AI in production—whether you support global enterprise systems, regulated industries, or edge devices.
Key concepts and examples at a glance:
| Focus Area | Primary Goal | Example Azure Services |
| ------------------------- | ------------------------------------ | ----------------------------------------------------------------------- |
| Authentication & Security | Protect credentials and limit access | Azure Key Vault, Azure AD, Managed Identities, Private Endpoints, VNETs |
| Monitoring & Optimization | Observe behavior and control costs | Azure Monitor, Log Analytics, Application Insights |
| Containerized Deployment | Package and run inference reliably | Docker, ACR, ACI, AKS |
Security and monitoring are foundational. Prefer managed identities and Key Vault over long-lived keys, and instrument your services early so you can measure and optimize before traffic grows.
Further reading and references
* [Azure Key Vault overview](https://learn.microsoft.com/azure/key-vault/general/overview)
* [Azure Active Directory fundamentals](https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-whatis)
* [Azure Monitor overview](https://learn.microsoft.com/azure/azure-monitor/overview)
* [Log Analytics overview](https://learn.microsoft.com/azure/azure-monitor/logs/log-analytics-overview)
* [Application Insights overview](https://learn.microsoft.com/azure/azure-monitor/app/app-insights-overview)
* [Azure Container Instances overview](https://learn.microsoft.com/azure/container-instances/container-instances-overview)
* [Azure Kubernetes Service (AKS) introduction](https://learn.microsoft.com/azure/aks/intro-kubernetes)
* [Azure Container Registry introduction](https://learn.microsoft.com/azure/container-registry/container-registry-intro)
# Monitoring Azure AI Services
Source: https://notes.kodekloud.com/docs/AI-102-Microsoft-Certified-Azure-AI-Engineer-Associate/Using-Azure-AI-Services-for-Enterprise-Applications/Monitoring-Azure-AI-Services/page
Guide to monitoring Azure AI services using metrics, logs, diagnostics, and alerts.
Monitoring Azure AI services ensures performance, reliability, and security for production workloads. Azure provides integrated monitoring features—Metrics, Diagnostic Settings, Logs, and Alerts—that help you track health, analyze behavior, and respond to incidents. This guide shows where to find those features in the Azure portal and how to use them effectively.
Key monitoring components at a glance:
| Component | Purpose | Typical use case |
| ------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| Alerts | Notify or automate when conditions occur | Notify on usage spikes, trigger remediation runbooks |
| Metrics | Numeric, time-series measurements (e.g., response time, request count) | Real-time dashboards and trend analysis |
| Diagnostic Settings | Configure export of logs and platform metrics to destinations | Centralize logs to Log Analytics, archive to Storage, or forward to Event Hubs |
| Logs | Detailed, timestamped records for auditing and troubleshooting | Forensics, compliance, and custom alerting with KQL |
This article walks through the Azure portal to locate these features for an Azure AI (Cognitive) resource (for example, Language or Vision services), and explains how to combine them for operational monitoring and security posture.
## Locate Metrics in the Azure portal
Steps to view metrics for a Cognitive Services / Azure AI resource:
1. In the Azure portal, open your Cognitive Services or specific Azure AI resource (e.g., Language service).
2. In the left-hand menu navigate to Monitoring > Metrics.
3. Select a metric (Total Calls, Latency, Throttled Requests, etc.), choose aggregation (Sum, Average, Count), and set the time range.
4. Add additional metrics to the chart to compare trends and spot correlations.
Metrics are ideal for dashboards, real-time monitoring, and identifying sudden spikes or gradual performance degradation.
Example: viewing the "Total Calls" metric for a deployed language resource:
Tips:
* Combine related metrics (e.g., Total Calls + Throttled Requests) to detect capacity or throttling issues.
* Pin metrics charts to Azure dashboards for consolidated operational views.
* Use appropriate aggregations for your scenario (Sum for totals, Average/Percentile for latency).
## Diagnostic settings and Logs
Diagnostic settings determine where resource logs and metrics are exported for deeper analysis, retention, or integration with SIEMs.
What diagnostic settings can export:
* Resource logs: request/response logs and resource-specific events.
* Platform metrics (where applicable).
* Activity and audit logs for Azure AI capabilities (for example, Azure OpenAI request usage).
Destinations supported:
| Destination | Use case |
| ----------------------- | ---------------------------------------------------------------------------------------------- |
| Log Analytics workspace | Query and analyze logs with Kusto Query Language (KQL); build custom dashboards and log alerts |
| Storage account | Long-term archival and compliance retention |
| Event Hub | Stream logs to third-party analytics or SIEMs (Splunk, external systems) |
| Partner solutions | Forward to available partner monitoring/analytics integrations |
To configure diagnostic settings:
1. Open your resource in the Azure portal.
2. Select Diagnostic settings > Add diagnostic setting.
3. Choose the log categories you need (Audit Logs, Request and Response Logs, Trace Logs, Azure OpenAI Request Usage, etc.).
4. Select one or more destinations (Log Analytics, Storage, Event Hub, Partner).
5. Save the diagnostic setting.
Diagnostic Settings do not automatically send logs anywhere — you must create a diagnostic setting and choose a destination (Log Analytics, Storage, Event Hub, etc.) to collect logs for analysis and retention.
Logs stored in Log Analytics are queryable using Kusto Query Language (KQL). Use KQL to:
* Perform forensics and investigations (who accessed what and when).
* Satisfy compliance and retention requirements.
* Create custom dashboards and log-based alert rules.
Useful references:
* [Diagnostic settings for Azure Monitor](https://learn.microsoft.com/azure/azure-monitor/essentials/diagnostic-settings)
* [Kusto Query Language (KQL)](https://learn.microsoft.com/azure/data-explorer/kusto/query/)
* [Azure Monitor Logs overview](https://learn.microsoft.com/azure/azure-monitor/logs/logs-overview)
Carefully consider data sensitivity before exporting request/response logs. Avoid sending Personally Identifiable Information (PII) or secrets to destinations unless you have proper data governance and encryption in place.
## Alerts: detect and respond
Azure Monitor alerts let you create rules that notify teams or trigger automation when metrics or logs meet defined conditions.
Alert types:
| Alert type | Triggers on | Use case |
| ------------------- | ----------------------------------- | ------------------------------------------------------------------ |
| Metric alerts | Numeric metric thresholds or trends | High error rates, CPU or request count thresholds |
| Log alerts | Results of a KQL query | Detect suspicious patterns in logs, failed authentication attempts |
| Activity Log alerts | Azure activity events | Resource creation, role changes, subscription-level events |
Typical alert rule workflow:
1. Define the scope (select the resource(s) to monitor).
2. Define the condition (metric threshold or KQL query and evaluation frequency).
3. Define actions by associating an Action Group (email, SMS, webhook, Logic App, Azure Function, Teams, PagerDuty, etc.).
4. Provide alert details (severity, description) and create the rule.
Use cases:
* Notify DevOps on usage spikes or quota exhaustion.
* Trigger automated remediation (e.g., scale-out, restart services).
* Escalate security incidents to on-call via PagerDuty or Teams.
Reference:
* [Azure Monitor alerts overview](https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview)
## Putting it together
* Metrics: Best for real-time numeric monitoring and dashboards.
* Diagnostic Settings + Logs: Centralize and retain logs for deep analysis, compliance, and alerting using KQL.
* Alerts: Bridge monitoring and operations by notifying teams and invoking automated responses.
A recommended monitoring approach:
1. Enable Metrics and pin key charts to an Azure dashboard.
2. Configure Diagnostic Settings to send resource logs to a Log Analytics workspace (and archive critical logs to Storage).
3. Create log- and metric-based alerts for operational and security thresholds.
4. Automate common remediations via Action Groups connected to Logic Apps or Functions.
5. Regularly review dashboard trends, alert history, and log queries to refine detection and reduce noise.
Monitoring is the foundation for keeping Azure AI services reliable, performant, and secure. With metrics, diagnostics, logs, and alerts configured, you can build dashboards, runbooks, and automated responses to maintain service health.
## Links and further reading
* [Azure Monitor documentation](https://learn.microsoft.com/azure/azure-monitor/)
* [Diagnostic settings for Azure Monitor](https://learn.microsoft.com/azure/azure-monitor/essentials/diagnostic-settings)
* [Kusto Query Language (KQL) quickstart](https://learn.microsoft.com/azure/data-explorer/kusto/query/)
* [Azure Monitor alerts overview](https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview)
# Securing Azure AI Services
Source: https://notes.kodekloud.com/docs/AI-102-Microsoft-Certified-Azure-AI-Engineer-Associate/Using-Azure-AI-Services-for-Enterprise-Applications/Securing-Azure-AI-Services/page
Guide on securing Azure AI services by using key rotation, Azure Key Vault, and Managed Identity to prevent credential leakage, enforce least privilege, and simplify secret rotation.
Protecting Azure AI resources from unauthorized access requires a layered approach. This guide covers three essential methods you can use together to reduce key leakage and operational risk: key rotation, storing secrets in Azure Key Vault, and using Managed Identity to avoid hardcoded credentials.
* Key rotation
* Key Vault storage
* Managed Identity
Why these controls matter
* Keys embedded in code or logs are easy to leak and can be used by an attacker to call your AI service, incur costs, or exfiltrate data.
* Combining centralized secret storage (Key Vault), automated identity (Managed Identity), and regular key rotation makes exposure less likely and limits the blast radius if a secret is compromised.
Comparison at a glance
| Resource Type | Primary Purpose | When to use |
| ---------------- | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------- |
| Key rotation | Limit exposure of compromised keys | Use for any long-lived secret; schedule per policy (monthly, quarterly) |
| Azure Key Vault | Centralize secrets, versioning, access control | Use to store API keys, connection strings, certificates |
| Managed Identity | Eliminate credentials in code by using Azure AD tokens | Use for Azure-hosted apps (App Service, VMs, Functions) to access Key Vault and other services |
## 1. Key rotation
Regularly regenerate (rotate) your access keys to reduce the time window an exposed key remains valid.
Zero-downtime rotation pattern (applies where resources provide two keys):
1. Configure your application to use the secondary key.
2. Regenerate the primary key.
3. Verify operation using the new primary key, then switch the application to use the primary key.
4. Regenerate the secondary key according to your rotation policy.
Best practices
* Select rotation frequency based on your compliance and risk posture (e.g., monthly, quarterly).
* Automate rotation and validation where possible to avoid human error.
* Never embed keys in source code, container images, or logs.
## 2. Key Vault storage
Use Azure Key Vault to centrally store keys, secrets, and certificates. Key Vault supports access control, auditing, and secret versioning.
Benefits
* Centralized management reduces accidental exposure via source control.
* Secret versioning lets you rotate without changing application code (if the app retrieves the latest version).
* Access to secrets can be audited and restricted via RBAC or Key Vault access policies.
How it works in practice
* Store your AI service API key as a secret in Key Vault.
* Applications fetch the secret at runtime (see Managed Identity below).
* When you rotate the secret in Key Vault, retrieving by name without a version returns the latest value, enabling seamless updates.
## 3. Managed Identity
Managed Identity eliminates credential handling in code by giving Azure resources an identity in Azure AD.
Typical flow
1. Your app authenticates using its Managed Identity.
2. The app requests the secret (API key) from Key Vault.
3. Key Vault returns the secret value.
4. The app uses the secret to call Azure AI Services.
Use Managed Identity wherever possible for Azure-hosted applications. It avoids hard-coded secrets and simplifies rotation and access control.
Example: retrieving a secret from Key Vault using Managed Identity (Python)
* Prerequisites: The Azure resource (e.g., App Service, VM, or Function) must have its Managed Identity enabled and be granted the Key Vault "get" permission. Install azure-identity and azure-keyvault-secrets packages.
```python theme={null}
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
import requests
# DefaultAzureCredential uses Managed Identity when running in Azure
credential = DefaultAzureCredential()
# Replace with your Key Vault URL
vault_url = "https://.vault.azure.net/"
client = SecretClient(vault_url=vault_url, credential=credential)
# Retrieve the secret (API key) by name (returns latest version if version not specified)
secret = client.get_secret("azure-ai-api-key")
api_key = secret.value
# Call the Azure AI endpoint using the retrieved key
endpoint = "https:///openai/deployments//completions?api-version=2023-05-15"
headers = {"api-key": api_key, "Content-Type": "application/json"}
payload = {"prompt": "Hello from managed identity!", "max_tokens": 16}
response = requests.post(endpoint, headers=headers, json=payload)
print(response.status_code, response.text)
```
Notes on implementation
* Grant the Managed Identity the least privilege necessary: use Azure RBAC or Key Vault access policies to grant the "get" permission for secrets.
* Use Key Vault secret versioning to track rotations; unless you specify a version, retrieving by name returns the current secret.
* Test rotation workflows: after rotating a secret, verify the app can read the updated secret before disabling or deleting older credentials.
Because the application fetches the current secret from Key Vault at runtime, you can rotate keys centrally without changing application code. This reduces downtime risk and limits the window in which an exposed credential is valid.
Never paste production keys or secrets in public repositories or documentation. Avoid logging secrets in plaintext. Use Key Vault and Managed Identity to minimize secret exposure.
Further reading and references
* [Azure Key Vault documentation](https://learn.microsoft.com/azure/key-vault/)
* [Managed identities for Azure resources](https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview)
* [Azure security documentation](https://learn.microsoft.com/security/azure-security)
* Microsoft Azure Security Technologies (AZ-500) course (example): [https://learn.kodekloud.com/user/courses/microsoft-azure-security-technologies-az-500](https://learn.kodekloud.com/user/courses/microsoft-azure-security-technologies-az-500)
Implementing these practices will help secure your Azure AI deployments by minimizing secret exposure, simplifying rotation, and enforcing least privilege access.
# Embeddings Vector Representations
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-1/Embeddings-Vector-Representations/page
How text embeddings map meaning to vectors enabling semantic search, document retrieval, and LLM grounding for robust paraphrase-insensitive search and recommendations
Embeddings convert text meaning into numeric vectors so machines can compare semantics rather than surface words. Instead of indexing raw keywords, embedding-based systems map words, phrases, and documents into a high-dimensional space where semantically similar items lie close together. This makes tasks like semantic search, clustering, and recommendation far more robust to paraphrase and synonyms.
For example, the phrases "employee vacation policy" and "staff time-off guidelines" use different wording but convey the same concept. An embedding model encodes both into vectors that occupy nearby positions in the embedding space, reflecting their semantic similarity.
An embedding model accepts text and returns a numeric vector (often with hundreds or thousands of dimensions — e.g., 1,536). Similar meaning produces similar numeric patterns; distance or similarity measures such as cosine similarity or dot product are used to identify related items. Words like "vacation" and "holiday" typically produce embeddings that are mathematically close.
When an employee asks, "Can I wear jeans to work?"
The typical retrieval pipeline works like this:
1. User query -> embed: Convert the user's question into an embedding vector.
2. Vector search: Compare the query embedding against stored document embeddings in a vector database (vector store) to find nearest neighbors.
3. Context assembly: Retrieve the top matching documents (e.g., HR policies, dress-code documents).
4. LLM grounding: Provide those retrieved documents as context to a large language model so it can generate a grounded answer — returning responses based on meaning and relevant documents rather than only keyword matches.
Practical benefits for an organization (e.g., TechCorp):
* Semantic search across a large document corpus (e.g., 500 GB) to find intent-matching documents.
* Robustness to paraphrase and synonyms: employees get correct answers even if they ask questions differently.
* Better relevance ranking by combining vector similarity with metadata and filters (date, author, department).
Similarity metrics and when to use them:
| Metric | Use Case | Notes |
| ------------------ | --------------------------------------------- | ----------------------------------------------------------------- |
| Cosine similarity | General semantic similarity | Robust to vector magnitude; widely used for embeddings |
| Dot product | When using models that use attention scores | Scales with vector norms; useful when magnitude encodes relevance |
| Euclidean distance | Clustering and nearest neighbor visualization | Sensitive to scaling; less common for normalized embeddings |
Normalize embeddings (L2 normalization) if you plan to use cosine similarity — this simplifies comparisons and often improves search quality. Combine vector similarity with metadata filters (time, department) to reduce false positives.
A concise example flow for the question "Can I wear jeans to work?":
* Convert the question to an embedding.
* Query the vector store to retrieve top N documents about attire, dress code, and HR policies.
* Provide those documents as context (prompting context window) to the LLM so it can answer with citations or specific policy language.
* Optionally, re-rank or filter results by document freshness or source trustworthiness.
Links and references
* [Introduction to Embeddings — Google Developers](https://developers.google.com/machine-learning/glossary/embedding)
* [OpenAI — Embeddings](https://platform.openai.com/docs/guides/embeddings)
* [Vector databases and nearest-neighbor search — Faiss](https://github.com/facebookresearch/faiss)
Further reading
* Semantic search: architectures that combine embeddings + vector DB + LLMs.
* Vector database options: Pinecone, Milvus, Weaviate, and Faiss.
* Prompting strategies: how to assemble retrieved documents into LLM prompts for grounded answers.
# How LLMs work in real time
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-1/How-LLMs-work-in-real-time/page
Explains how large language models use context windows in real time and practical methods to enable accurate queries over private documents using chunking, embeddings, vector search, and RAG.
This lesson explains what happens when you ask an AI a question, how large language models (LLMs) use context, and practical strategies for letting models answer questions about private documents.
When you ask an AI a question, the reply usually comes from a family of models called large language models (LLMs). LLMs surged in popularity after the release of [ChatGPT](https://openai.com/blog/chatgpt) in late 2022, as researchers and companies scaled both model size and training data to improve performance.
Popular LLMs such as [OpenAI’s GPT series](https://openai.com/gpt-4), [Anthropic’s Claude](https://www.anthropic.com/claude), and [Google’s Gemini](https://gemini.google/) are built on the transformer architecture and trained on extremely large corpora. Training datasets can reach tens of trillions of tokens drawn from thousands of domains — healthcare, law, code, science, and more.
Pretraining datasets do not include your private company files (for example, TechCorp’s 500 GB of internal documents) unless they were explicitly added to the training data. To get an LLM to answer questions about private data, you must provide that data to the model at query time.
One common way to supply private data to an LLM is to include relevant material in the conversation’s context — a form of short-term memory the model uses while the conversation is active. This short-term memory is called the context window.
Here are typical context-window sizes for various models:
| Model / Variant | Approx. context window |
| ---------------------------- | ------------------------ |
| xAI Grok-4 | \~256,000 tokens |
| Anthropic Claude Opus | \~200,000 tokens |
| Google Gemini (Pro variants) | up to \~1,000,000 tokens |
| Smaller “nano” / base models | 2,000–4,000 tokens |
The context window defines how much text the model can attend to at once. A token is roughly three quarters of a typical English word, so token counts translate approximately to word counts. Practical consequences:
* Smaller models (2k–4k tokens) are well-suited to short interactions and lower-latency use cases.
* Larger models with huge windows (hundreds of thousands to a million tokens) can handle long documents, entire books, or many source files at once.
* Regardless of size, only the tokens that are actually included in the context are visible to the model at query time.
Think of the context window as short-term memory: it can hold only so many facts and details simultaneously. Irrelevant content in the supplied context consumes token budget and can distract the model, while extremely large knowledge stores (e.g., a company’s 500 GB of documents) cannot be loaded into context all at once.
Here’s a simple example to illustrate relevance extraction from context:
Sally and Bob own an apple farm.\
Sally has 14 apples.\
Apples are often red.\
12 is a nice number.\
Bob has no red apples, but he has two green apples.\
Green apples often taste bad.
How many apples do they all have?
To answer correctly, the model must extract the relevant facts (Sally has 14, Bob has 2) and ignore irrelevant details (apple color, taste, or unrelated numbers). The correct total is 16.
This example highlights two practical limits of context windows:
* Irrelevant information in the context consumes token budget and can distract the model.
* Only a fraction of a very large knowledge store can be presented to the model at one time.
Strategies to provide relevant private data at query time
* Document chunking: split large files into smaller, semantically coherent chunks that fit the context window.
* Embeddings + vector search: convert chunks to embeddings, perform similarity search to find the most relevant passages, and surface those passages in the prompt.
* Retrieval-augmented generation (RAG): combine retrieval (vector search) with generation so the model uses retrieved documents to answer queries.
* Summaries & hierarchical retrieval: use summaries to locate relevant sections, then retrieve full content for finer-grained answers.
* External tools & workflows: call external search engines, databases, or specialized tools to fetch data the model can use.
| Approach | When to use | Example |
| -------------------------- | --------------------------------------------------- | ---------------------------------------------------------------------- |
| Chunking | Large documents that exceed context windows | Break a 100-page manual into 2–5 page chunks |
| Embeddings + vector search | Fast retrieval of semantically similar passages | Search index of meeting notes to find relevant discussions |
| RAG | QA over large corpora where accuracy matters | Combine vector search with a model to answer customer support queries |
| Summarization | Reduce token usage when exact details aren't needed | Summarize monthly reports, then retrieve specific sections if required |
When designing systems that use private documents with LLMs, combine embeddings-based retrieval with concise prompt engineering (and fine-grained chunking) to ensure the model receives only the most relevant context within its token budget.
Further reading and references
* Transformer architecture: [https://en.wikipedia.org/wiki/Transformer\_(machine\_learning\_model)](https://en.wikipedia.org/wiki/Transformer_\(machine_learning_model\))
* Retrieval-augmented generation (RAG): [https://en.wikipedia.org/wiki/Retrieval-augmented\_generation](https://en.wikipedia.org/wiki/Retrieval-augmented_generation)
* OpenAI GPT: [https://openai.com/gpt-4](https://openai.com/gpt-4)
* Anthropic Claude: [https://www.anthropic.com/claude](https://www.anthropic.com/claude)
* Google Gemini: [https://gemini.google/](https://gemini.google/)
# How LangChain works
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-1/How-LangChain-works/page
Explains how LangChain composes LLMs, embeddings, vector stores, memory, and tools to build retrieval augmented conversational agents and workflows for production chatbots
Now that we understand how LLMs and embeddings function, we need a system that ties those primitives together into a reliable, maintainable product.
TechCorp needs a chatbot that lets customers ask questions about company policy, product details, and support issues. The system must:
* Remember conversation history
* Access the company knowledge base (documents, FAQs, manuals)
* Handle complex multi-step interactions and take actions when needed
A naive implementation might call an LLM provider's SDK (for example, [OpenAI](https://learn.kodekloud.com/user/courses/introduction-to-openai)) for every user message. But that leaves several engineering gaps: storing chat messages, maintaining conversational context, performing semantic search over internal documents, routing calls to internal tools, and keeping the solution portable across providers (OpenAI → Anthropic → Google). What looks small quickly grows into a large integration project.
LangChain provides an abstraction layer that addresses these gaps with composable, standardized components and interfaces.
Understanding LLM vs Agent
When you call a large language model (GPT, Claude, Gemini) directly, it acts as a static "brain" that generates answers from its training and prompt context. An agent, by contrast, augments that brain with autonomy, memory, and access to external tools — enabling it to decide which steps to take to satisfy a user request.
For TechCorp’s support scenario, consider the question: "What's your policy on refunds for a product that arrived damaged?" An agent might:
* Retrieve the relevant policy from the company knowledge base,
* Check prior conversation context to confirm whether the customer already provided an order number,
* Call an internal customer-database tool to validate purchase details,
* Open a support ticket if required — without you hard-coding an if/else flow for each step.
Why use LangChain?
LangChain exposes composable building blocks that map directly to the integration concerns above:
* Chat models: unified interfaces to LLM providers (OpenAI, Anthropic, Google). Switching providers often becomes a single-line change.
* Memory: session-aware memory components to store and retrieve conversation state without implementing a custom schema.
* Vector DB integration: standard adapters for vector databases (Chroma, Pinecone, etc.) so semantic search is consistent across providers.
* Embeddings: standardized embedding components to convert documents into vectors.
* Tools: easy definitions for external tool access (customer DB queries, web search, ticket creation), which agents can call when appropriate.
Without LangChain, you must implement API clients, connection management, storage layers, embedding pipelines, semantic search, memory systems, and tool routing yourself — complexity multiplies fast.
LangChain’s component library typically includes connectors and classes such as chat model wrappers, vectorstore adapters, embedding wrappers, memory classes for chat history, and a mechanism to define tools that agents can call. The agent orchestrates these components based on conversation context and system prompts.
LangChain components at a glance
| Component Type | Purpose | Example |
| ------------------------ | -------------------------------------------------------- | ----------------------------------------------- |
| Chat model | Conversational LLM wrapper supporting multiple providers | `ChatOpenAI(model_name="gpt-3.5-turbo")` |
| Memory | Stores session conversation history and state | `ConversationBufferMemory` |
| Embeddings | Converts text/documents to numeric vectors | `OpenAIEmbeddings()` |
| Vector store / Retriever | Indexes vectors and supports semantic search | `Chroma`, `Pinecone` |
| Chains / Agents | Compose LLM, retriever, memory, and tools into workflows | `ConversationalRetrievalChain` |
| Tools | Integrations for external APIs and actions | Customer DB query, web search, ticketing system |
Putting it together (example)
This concise example shows one way to wire a chat model, embeddings, vectorstore, memory, and a conversational retrieval chain — the core pattern for a retrieval-augmented chat agent. Import paths and class names can change between LangChain releases; check the documentation for your version.
```python theme={null}
from langchain.chat_models import ChatOpenAI, ChatAnthropic
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
# Choose your LLM provider
llm = ChatOpenAI(model_name="gpt-3.5-turbo")
# Alternative provider example:
# Memory for storing conversational history
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
# Embeddings convert documents into vectors
embedding = OpenAIEmbeddings()
# Vector store that holds TechCorp documents (indexed using the embeddings)
db = Chroma(collection_name="techcorp_docs", embedding_function=embedding)
# Create a conversational retrieval chain that uses the LLM + vector DB + memory
qa_chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=db.as_retriever(),
memory=memory
)
# Run a query through the chain
response = qa_chain.run("What is TechCorp's customer data policy?")
print(response)
```
Note: LangChain import locations and class names can change across releases. If an import fails, consult the LangChain docs for your installed version. Also ensure environment variables for provider API keys (e.g., OPENAI\_API\_KEY, ANTHROPIC\_API\_KEY) are set before running the code.
How the agent uses components
* LLM: natural-language reasoning and response generation.
* Embeddings: convert company documents into dense vectors for semantic indexing.
* Vector store / Retriever: performs semantic search over indexed documents and returns relevant context to the agent.
* Memory: holds recent chat history so replies are context-aware and coherent across turns.
* Tools: allow the agent to call external APIs or perform actions (customer DB lookups, ticket creation, web searches).
This modularity makes extending the agent straightforward: add new tools, swap the LLM provider, or change the vectorstore with minimal code changes.
Warning: Avoid sending sensitive PII or confidential documents to third-party LLMs unless you have contracts and controls in place. Review your data privacy, retention, and compliance requirements before indexing private documents or integrating internal systems.
Conclusion and next steps
Using LangChain speeds up building production-ready conversational agents by providing tested building blocks for common integration tasks: RAG (retrieval-augmented generation), memory management, tool invocation, and multi-provider support. Start by:
1. Defining your data sources (documents, databases, support tickets).
2. Choosing an embedding provider and vector store (Chroma, Pinecone).
3. Wiring a conversational chain with memory and a retriever.
4. Adding tools for any external actions your agent must perform.
Links and references
* [LangChain — learn.kodekloud course](https://learn.kodekloud.com/user/courses/langchain)
* [OpenAI Docs](https://platform.openai.com/docs)
* Chroma: [https://www.trychroma.com/](https://www.trychroma.com/)
* Pinecone: [https://www.pinecone.io/](https://www.pinecone.io/)
* Retrieval-augmented generation (RAG) overview: [https://en.wikipedia.org/wiki/Retrieval-augmented\_generation](https://en.wikipedia.org/wiki/Retrieval-augmented_generation)
Now that you’ve seen the conceptual elements and a practical snippet, you should have a clear idea of how LangChain brings together LLMs, embeddings, vector stores, memory, and tool integration to build reliable conversational agents.
# Introduction to AI Agents
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-1/Introduction-to-AI-Agents/page
Hands-on overview of AI agents and related technologies including tokens, embeddings, RAG, vector databases, orchestration libraries, MCPs, and practical end-to-end project for building robust AI applications.
AI has advanced rapidly over the past few years. Today’s practical toolkit for building intelligent applications includes concepts and technologies such as prompt engineering, context windows, tokens, embeddings, Retrieval-Augmented Generation (RAG), vector databases, Model Context Protocols (MCPs), orchestration libraries like LangChain and LangGraph, and AI agents. This lesson gives a concise, hands-on overview so you can understand how these pieces fit together and start building right away.
This lesson assumes no prior knowledge. It’s structured around a single, practical project that integrates fundamental AI concepts (tokens, embeddings, context windows, prompt design) with retrieval and orchestration (RAG, vector databases, LangChain/LangGraph, MCPs, and agents).
We’ll cover these topics and why they matter:
| Topic | What it is | Why it matters |
| -------------------------------------- | --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| Tokens, context windows, prompt design | The basic units and limits for language model input and strategies for guiding behavior | Impacts cost, capability, and response quality |
| Embeddings | Numerical vectors that represent text semantics | Enables semantic search and similarity-based retrieval |
| Retrieval-Augmented Generation (RAG) | Combining retrieval from a knowledge store with generation by a model | Improves factual accuracy and relevance for LLM outputs |
| Vector databases | Storage and indexing systems for embeddings | Fast, scalable similarity search for RAG pipelines |
| LangChain / LangGraph | Orchestration libraries for composing models, prompts, and tools | Simplifies building complex, multi-step AI workflows (agents) |
| MCPs (Model Context Protocols) | Conventions for how models share context and tools | Helps agents coordinate model calls and external tools |
| AI Agents | Systems that use models + tools to perform tasks autonomously | Enables multi-step, tool-enabled workflows like data lookups, API calls, and reasoning |
We’ll progress in a practical order:
1. Core AI fundamentals (tokens, embeddings, context windows, prompt design)
2. Retrieval-Augmented Generation and vector databases — how embeddings are stored and searched
3. Orchestration with LangChain and LangGraph, and how they help build agents
4. MCPs and agent coordination across models and tools
5. A single end-to-end project that ties these components together
Along the way you’ll see how each layer interacts with the others so you can design robust, production-ready AI applications that are both accurate and cost-effective. Useful references and deeper-dive resources are linked inline for each topic.
# Practice Labs LangChain
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-1/Practice-Labs-LangChain/page
Hands-on LangChain tutorial demonstrating environment checks, reducing SDK boilerplate, multi-model A/B testing, prompt templates, output parsers, and chain composition for building LLM pipelines
LangChain provides a unified, higher-level interface for working with multiple model providers. With LangChain you can switch from OpenAI to Google Gemini or xAI Grok with minimal code changes—often just a model name or a single class swap—while keeping most of your application logic intact.
In this lesson/article we will:
* Verify the environment and dependencies
* Compare native SDK boilerplate vs. LangChain
* Demonstrate multi-model support (A/B testing)
* Use prompt templates to avoid prompt duplication
* Parse model outputs into structured data
* Compose chains to build clean pipelines
***
## Environment verification
Before starting, run the verification script to confirm:
* Python is the expected version
* You are inside a virtual environment
* Required packages (langchain, openai, pydantic, etc.) are installed
* API keys and base URLs are set in environment variables
Example commands:
```bash theme={null}
# Activate the venv and run the verification script
source /root/venv/bin/activate
python /root/code/verify_environment.py
```
Expected (cleaned-up) output example:
```text theme={null}
🔍 Verifying LangChain Lab Environment
=========================================================
✅ Python version: 3.12.3
📦 Virtual Environment Check:
✅ Running in virtual environment
📚 Required Packages:
✅ langchain
✅ openai
✅ other dependencies...
```
Once this check passes, continue to the tasks below.
***
## Quick comparison: Native SDK vs. LangChain
Use this table to get a high-level view of the differences when calling chat models directly vs. using LangChain:
| Resource Type | Native SDK (example) | LangChain (wrapper) |
| ------------------- | --------------------------------------------- | -------------------------------------------- |
| Setup lines | Several lines to configure client & messages | Few lines to initialize ChatModel wrapper |
| Message handling | Provider-specific message objects / responses | Standardized call pattern (list of messages) |
| Provider swaps | Often change code and response parsing | Usually change model class or model\_name |
| Reuse & composition | Manual orchestration | Built-in PromptTemplate, Chains, Parsers |
***
## Task 1 — Boilerplate: Native SDK vs. LangChain
Native SDKs often require explicit client setup and manual message handling. Example (OpenAI SDK pseudocode):
```python theme={null}
# Example using OpenAI SDK (simplified)
import os
from openai import OpenAI # pseudocode; actual import may differ
api_key = os.getenv("OPENAI_API_KEY")
base_url = os.getenv("OPENAI_API_BASE")
client = OpenAI(api_key=api_key, base_url=base_url)
prompt = "Explain cloud computing in one sentence"
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}]
)
result = response.choices[0].message.content
print(result)
```
With LangChain you typically reduce that to a few lines by using a chat model wrapper and the standardized message schema:
```python theme={null}
# Using LangChain's chat model wrapper
import os
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage
llm = ChatOpenAI(
model_name="gpt-4",
openai_api_key=os.getenv("OPENAI_API_KEY"),
openai_api_base=os.getenv("OPENAI_API_BASE"),
)
prompt = "Explain cloud computing in one sentence"
response = llm([HumanMessage(content=prompt)]) # call with a list of messages
print(response.content)
```
LangChain provides a consistent high-level API for chat and LLM calls. You still need provider-specific credentials and sometimes provider-specific classes, but swapping providers usually requires only a small change (model\_name or class).
***
## Task 2 — Multi-Model Support (A/B testing)
LangChain makes it easy to initialize multiple providers and run the same prompt against each to compare outputs for A/B testing, quality vs. cost analysis, or feature testing. Below is a compact pattern to initialize multiple model objects and iterate over them.
```python theme={null}
# task_2_multi_model.py
import os
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage
print("\n🚀 Task 2: Multi-Model Support with LangChain")
print("=" * 50)
test_prompt = "Explain cloud computing in one sentence"
# Example initializations (replace with provider-specific wrappers and creds in real use)
openai_llm = ChatOpenAI(
model_name="gpt-4",
openai_api_key=os.getenv("OPENAI_API_KEY"),
openai_api_base=os.getenv("OPENAI_API_BASE"),
)
# NOTE: The following examples illustrate a unified call pattern.
# In production, use provider-specific wrappers (e.g., Vertex AI client for Gemini)
google_llm = ChatOpenAI(
model_name="google/gemini-2.5-flash", # illustrative placeholder
openai_api_key=os.getenv("OPENAI_API_KEY"),
openai_api_base=os.getenv("OPENAI_API_BASE"),
)
xai_llm = ChatOpenAI(
model_name="xai/grok-medium", # illustrative placeholder
openai_api_key=os.getenv("OPENAI_API_KEY"),
openai_api_base=os.getenv("OPENAI_API_BASE"),
)
for name, llm in [("OpenAI", openai_llm), ("Google", google_llm), ("X.AI", xai_llm)]:
try:
response = llm([HumanMessage(content=test_prompt)])
snippet = response.content[:200] # show a short snippet
print(f"{name}: {snippet}...\n")
except Exception as e:
print(f"{name}: Error invoking model: {e}\n")
# create marker for completion
import os
os.makedirs("/root/markers", exist_ok=True)
with open("/root/markers/task2_complete.txt", "w") as f:
f.write("COMPLETED")
```
Sample comparison output:
```text theme={null}
Model Comparison - Same Prompt, Different Models
Prompt: 'Explain cloud computing in one sentence'
OpenAI: Cloud computing is the delivery of computing resources and services, such as storage, processing,...
Google: Cloud computing delivers on-demand computing services—including servers, storage, databases, and networks...
X.AI: Cloud computing is the delivery of on-demand computing resources, such as servers, storage, and databases...
```
This pattern simplifies A/B experiments: same code, different model instances.
Model identifiers and client initialization vary across providers. The examples above use placeholders for non-OpenAI providers—swap to provider-specific wrappers (e.g., Vertex AI for Google Gemini) and ensure correct credentials and regional endpoints before running in production.
***
## Task 3 — Prompt templates
Avoid duplicating prompt strings across your codebase by using reusable PromptTemplate objects. Templates let you format input dynamically while keeping a consistent prompt structure.
```python theme={null}
# task_3_prompt_templates.py
import os
from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage
print("🧑💻 Task 3: Dynamic Prompt Templates")
print("=" * 50)
# Define a reusable template with placeholders
template = PromptTemplate(
input_variables=["topic", "style"],
template="Explain {topic} in {style}"
)
# Initialize the LLM
llm = ChatOpenAI(
model_name="gpt-4",
openai_api_key=os.getenv("OPENAI_API_KEY"),
openai_api_base=os.getenv("OPENAI_API_BASE"),
temperature=0.7
)
# Format the template with specific values
test_prompt = template.format(topic="artificial intelligence", style="exactly 5 words")
print(f"🛰️ Sending to AI: {test_prompt}\n")
# Send to the model
response = llm([HumanMessage(content=test_prompt)])
print("AI Response:", response.content)
```
Template benefits:
* Single source of truth for prompt patterns
* Easy to update structure or wording in one place
* Clean separation of prompt logic and application data
* Works well with LLMChain for reuse across pipelines
***
## Task 4 — Output parsers (structured outputs)
For production systems you usually need structured outputs (JSON, typed objects). LangChain supports output parsers such as PydanticOutputParser to ensure responses match expected schemas.
```python theme={null}
# task_4_output_parsers.py
import os
from pydantic import BaseModel
from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.output_parsers import PydanticOutputParser
from langchain.schema import HumanMessage
# Define the expected structure with Pydantic
class SummaryModel(BaseModel):
summary: str
keywords: list[str]
parser = PydanticOutputParser(pydantic_object=SummaryModel)
template = PromptTemplate(
input_variables=["topic"],
template=(
"Provide a short summary and a list of 3 keywords for the topic: {topic}.\n"
"Respond as JSON that matches the SummaryModel schema."
),
)
llm = ChatOpenAI(
model_name="gpt-4",
openai_api_key=os.getenv("OPENAI_API_KEY"),
openai_api_base=os.getenv("OPENAI_API_BASE"),
temperature=0.2
)
prompt = template.format(topic="artificial intelligence")
response = llm([HumanMessage(content=prompt)])
raw_text = response.content
print("Raw AI Response:", raw_text)
# Parse into structured data
parsed = parser.parse(raw_text)
print("Parsed object:", parsed)
print("Parsed type:", type(parsed))
```
Using parsers avoids fragile ad-hoc string parsing and gives you typed Python objects ready for downstream usage (databases, APIs, UIs).
***
## Task 5 — Chain composition (building pipelines)
LangChain makes composition straightforward. Use LLMChain to bind prompts and models, then post-process with parsers or helper functions to create readable, reusable pipelines.
```python theme={null}
# task_5_chain_composition.py
import os
from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
print("\n🧠 Chain 1: Simple Analysis")
print("=" * 50)
analysis_prompt = PromptTemplate(
input_variables=["technology"],
template="Analyze {technology} and provide pros and cons in 2-3 sentences."
)
llm = ChatOpenAI(
model_name="gpt-4",
openai_api_key=os.getenv("OPENAI_API_KEY"),
openai_api_base=os.getenv("OPENAI_API_BASE"),
temperature=0.3
)
analysis_chain = LLMChain(llm=llm, prompt=analysis_prompt)
# Invoke the chain with one call
result = analysis_chain.run({"technology": "blockchain"})
print("📥 Input: 'Analyze blockchain'")
print("✅ Output:", result)
```
For more complex pipelines you can chain or sequence multiple components:
* PromptTemplate -> LLM (LLMChain) -> Output parser -> Database save -> Notification
Conceptual example:
```Python theme={null}
prompt = template.format(...)
response = llm([HumanMessage(content=prompt)])
parsed = parser.parse(response.content)
save_to_db(parsed)
send_email_notification(parsed)
```
LLMChain plus parsers and helper functions keep this pattern concise and testable.
***
## Summary
By following the exercises above you should now understand how LangChain helps you:
* Reduce boilerplate versus native SDK code paths
* Experiment with multiple models for A/B testing
* Create reusable prompt templates to avoid duplication
* Produce structured outputs using parsers like PydanticOutputParser
* Compose chains for readable, maintainable pipelines
Keep experimenting with more complex parser schemas, multi-step chains, and provider-specific integrations to adapt this pattern for production workloads.
***
## Links and References
* LangChain Documentation: [https://langchain.readthedocs.io/](https://langchain.readthedocs.io/)
* OpenAI API: [https://platform.openai.com/docs](https://platform.openai.com/docs)
* Google Vertex AI (Gemini): [https://cloud.google.com/vertex-ai](https://cloud.google.com/vertex-ai)
* Pydantic: [https://pydantic-docs.helpmanual.io/](https://pydantic-docs.helpmanual.io/)
* xAI / Grok (vendor): check vendor docs for model identifiers and APIs
# Practice Labs Master Prompt Engineering
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-1/Practice-Labs-Master-Prompt-Engineering/page
Guide to mastering prompt engineering with LangChain using zero-shot, one-shot, few-shot, and chain-of-thought techniques with practical examples and best practices
Master prompt engineering using LangChain to get consistent, useful, and controllable outputs from LLMs. This guide demonstrates practical prompting techniques — Zero-Shot, One-Shot, Few-Shot, and Chain-of-Thought — with runnable examples and recommended best practices.
Why this matters: LLMs often produce vague, inconsistent, or incomplete responses when prompts lack structure. The techniques below help you control format, tone, length, and reasoning so outputs match your requirements.
High-level tip: choose the prompting technique that matches your goal — speed, format consistency, tone, or complex reasoning — and provide explicit constraints (format, length, audience) to get predictable outputs.
Environment verification
Before starting the exercises, confirm your development environment is ready (virtualenv activated, LangChain installed, OpenAI credentials configured, and an LLM connection working). This prevents runtime errors and allows you to focus on prompt quality during experiments.
Run this one-line environment check:
```bash theme={null}
source /root/venv/bin/activate && python /root/code/verify_environment.py
```
Expected verification output (example):
```text theme={null}
🔧 Verifying Prompt Engineering Lab Environment...
========================================
✅ Virtual environment is active
✅ LangChain available (version: 0.3.27)
✅ OpenAI configuration found
API Base: https://dev.kk-ai-keys.kodekloud.com/v1
✅ LLM connection test passed
🎉 All environment checks passed!
Your prompt engineering lab environment is ready.
```
Do not commit API keys or secret files to version control. Keep credentials in environment variables or a secure secret store and verify access only from trusted machines.
Once verification passes and prompt utilities are available, proceed to the tasks below. Each task includes the concept, an example prompt or script, expected behavior, and best practices to help you reproduce consistent results.
***
## Task 1 — Zero-Shot Prompting
Zero-shot prompting asks the model to perform a task with no examples. The quality of the output depends heavily on how explicit and constrained the instruction is.
Key idea: prefer a specific instruction that includes audience, jurisdiction, required sections, and constraints (word count, tone, or format).
Illustrative Python comparison (vague vs. specific zero-shot prompts):
```python theme={null}
# task_1_zero_shot.py
def main(llm):
vague_prompt = "Write a privacy policy."
vague_response = llm.invoke(vague_prompt)
print(f"\nVague response preview: {vague_response.content[:100]}...")
print("Problem: Too generic, not useful for our company!")
print("\n✅ Specific Zero-Shot Prompting")
specific_prompt = (
"Write a 200-word data privacy policy for European customers "
"in compliance with the [General Data Protection Regulation (GDPR)](https://gdpr.eu/). "
"Include retention (30 days), data subject rights, and data transfer rules."
)
specific_response = llm.invoke(specific_prompt)
print(f"\nSpecific response preview: {specific_response.content[:200]}...")
print("Success: Clear, actionable, company-specific!")
print("\n📊 Comparison Results:")
print(f"Vague response length: {len(vague_response.content)} characters")
print(f"Specific response length: {len(specific_response.content)} characters")
```
Example console output (trimmed):
```text theme={null}
Vague response preview: We are committed to protecting your privacy...
Problem: Too generic, not useful for our company!
✅ Specific Zero-Shot Prompting
Specific response preview: We are committed to protecting the privacy of our European customers in accordance with the GDPR. This policy covers...
Success: Clear, actionable, company-specific!
📊 Comparison Results:
Vague response length: 263 characters
Specific response length: 1369 characters
```
Zero-shot best practices:
* State the exact task and desired length.
* Define context (jurisdiction, audience, domain).
* List required sections or bullet points the output must include.
* Constrain format where necessary (e.g., JSON, Markdown, or numbered sections).
***
## Task 2 — One-Shot Prompting
One-shot prompting supplies a single example that demonstrates the desired format, tone, or structure. It’s useful when you want the model to reproduce a template or layout across many inputs.
Example: Provide a refund policy template as the one-shot example and ask the model to produce a remote work policy using the same structure.
One-shot example (refund policy template):
```text theme={null}
1. Eligibility: Within 30 days of purchase
2. Conditions: Product unused and in original packaging
3. Process: Submit request via support@company.com
4. Timeline: Refund processed within 5-7 business days
5. Exceptions: Digital products and custom orders non-refundable
```
Then ask the model:
```text theme={null}
🧪 Using the template above, create a REMOTE WORK POLICY for our company with the same five-section format.
```
Generated result (example):
```text theme={null}
REMOTE WORK POLICY
1. Eligibility: Employees approved by management for remote work
2. Conditions: Maintain a dedicated workspace and reliable internet connection
3. Process: Submit remote work request to HR at hr@company.com
4. Timeline: Approval communicated within 3 business days
5. Exceptions: Positions requiring on-site presence and confidential projects not eligible for remote work
```
One-shot benefits:
* Enforces a single-template formatting.
* Fast to set up for repetitive, structured documents.
* Good when you want to preserve a strict layout without many examples.
***
## Task 3 — Few-Shot Prompting
Few-shot prompting gives the model several diverse examples so it can learn format, tone, and response patterns. This technique is ideal for customer support, marketing copy, or any content that requires consistent voice across variations.
Example few-shot training set (customer support style examples):
```text theme={null}
Customer Issue: The product arrived damaged.
Support Response: I'm so sorry to hear that. Please send a photo to support@company.com so we can open a replacement or refund immediately. We'll respond within 2 business days.
Customer Issue: I haven't received my order.
Support Response: I apologize for the delay. Please share your order number and I'll check the shipping status. Expect an update within 24 hours.
Customer Issue: I need to change my billing address.
Support Response: Thanks for letting us know. Please confirm the new billing address and we'll update it for future invoices. This change will reflect within 1 business day.
```
New prompt and model output:
```text theme={null}
🧾 New customer issue:
Product not working
🤖 AI Response:
I'm sorry to hear the product isn't working as expected. Could you please provide a brief description of the issue and any error messages? Meanwhile, I'll check if there are known troubleshooting steps or recalls related to your product.
```
Quick response analysis example:
```text theme={null}
✓ Shows empathy: True
✓ Takes action (asks for next steps): True
✓ Provides timeline: False
Quality Score: 2/3
```
Few-shot advantages:
* Learns subtleties of tone and phrasing across examples.
* Keeps responses consistent across agents or channels.
* Reduces need for labeled fine-tuning for many use-cases.
***
## Task 4 — Chain-of-Thought (CoT) Prompting
Chain-of-Thought prompting encourages the model to expose intermediate reasoning steps. This produces more accurate and defensible answers for complex or multi-step tasks.
Use CoT when you need the model to enumerate assumptions, weigh options, or provide a stepwise troubleshooting path.
Example LangChain prompt templates (fixed and syntactically correct):
```python theme={null}
# task_4_chain_of_thought.py
from langchain.prompts import PromptTemplate, FewShotPromptTemplate
# Example list of examples (each is a dict with 'input' and 'output')
examples = [
{"input": "User cannot connect to WiFi", "output": "Step 1: Ask for error details. Step 2: Confirm SSID and password. Step 3: Suggest restart and driver update."},
{"input": "App crashes on startup", "output": "Step 1: Ask for device and OS. Step 2: Ask for app version and logs. Step 3: Suggest clearing cache or reinstalling."},
{"input": "Invoice not received", "output": "Step 1: Verify order number. Step 2: Confirm billing email. Step 3: Resend invoice and confirm delivery."}
]
# Create the example template
example_prompt = PromptTemplate(
template="Customer Issue: {input}\nSupport Response: {output}",
input_variables=["input", "output"]
)
# Create the few-shot prompt template
few_shot_prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_prompt,
prefix="You are a helpful customer support agent. Here are examples of how to break problems down step-by-step:\n\n",
suffix="Customer Issue: {input}\nSupport Response:",
input_variables=["input"]
)
def generate_support_response(llm, user_issue):
prompt = few_shot_prompt.format(input=user_issue)
response = llm.invoke(prompt)
return response.content
```
Simple CoT instruction pattern:
```text theme={null}
When solving the problem, think through it step-by-step:
1. Identify the main issue.
2. List possible causes.
3. Propose troubleshooting steps in order of likelihood.
4. Provide a recommended next action.
```
CoT best practices:
* Provide worked examples that demonstrate intermediate steps.
* Ask the model to enumerate assumptions and order steps by likelihood.
* Use models/configurations that support longer contexts for full reasoning chains.
* Prefer CoT when correctness and traceability matter.
***
## Task 5 — Technique Showdown (Comparison)
Compare the techniques by running the same task through each style and evaluating differences in structure, tone, and completeness.
Example Python script comparing all four techniques:
```python theme={null}
# task_5_comparison.py
def main(llm):
test_problem = "Create an employee remote work policy"
print(f"🧪 Test Problem: {test_problem}\nTesting all 4 prompting techniques...\n")
results = {}
# 1. ZERO-SHOT PROMPTING
print("1️⃣ Zero-Shot Prompting")
zero_shot_result = llm.invoke(test_problem)
results["zero_shot"] = zero_shot_result.content
print(f"Response length: {len(zero_shot_result.content)} characters")
print(f"Preview: {zero_shot_result.content[:100]}...\n")
# 2. ONE-SHOT PROMPTING
print("2️⃣ One-Shot Prompting")
one_shot_example = (
"REMOTE WORK POLICY\n"
"1. Eligibility: ...\n"
"2. Conditions: ...\n"
"3. Process: ...\n"
"4. Timeline: ...\n"
"5. Exceptions: ..."
)
one_shot_prompt = one_shot_example + "\n\nPlease create a remote work policy in the same format for our company."
one_shot_result = llm.invoke(one_shot_prompt)
results["one_shot"] = one_shot_result.content
print(f"Response length: {len(one_shot_result.content)} characters\n")
# 3. FEW-SHOT PROMPTING
print("3️⃣ Few-Shot Prompting")
few_shot_prompt = "Examples:\n" + one_shot_example + "\n\n[additional examples]\n\nNow create a remote work policy:"
few_shot_result = llm.invoke(few_shot_prompt)
results["few_shot"] = few_shot_result.content
print(f"Response length: {len(few_shot_result.content)} characters\n")
# 4. CHAIN-OF-THOUGHT PROMPTING
print("4️⃣ Chain-of-Thought Prompting")
cot_prompt = (
"You are an expert HR advisor. When drafting the policy, think through it step-by-step:\n"
"1. Identify objectives.\n2. Define eligibility and conditions.\n3. Describe the process and timelines.\n4. Note exceptions and compliance.\n\n"
"Now create an employee remote work policy based on that reasoning."
)
cot_result = llm.invoke(cot_prompt)
results["chain_of_thought"] = cot_result.content
print(f"Response length: {len(cot_result.content)} characters\n")
# Comparative summary
for k, v in results.items():
print(f"{k}: {len(v)} characters")
```
Typical comparative observations:
* Zero-Shot: fastest but may miss company specifics or required sections.
* One-Shot: enforces a strict format from a single template.
* Few-Shot: matches tone and variations across multiple examples.
* Chain-of-Thought: produces longer, structured reasoning and more comprehensive policies.
Comparison table (quick reference):
| Technique | Primary Strength | When to Use | Example Outcome |
| ---------------- | -------------------- | -------------------------------------- | -------------------------------------- |
| Zero-Shot | Fast, minimal setup | Quick answers, prototypes | Short, generic policy |
| One-Shot | Template enforcement | When strict format matters | Policy that matches template exactly |
| Few-Shot | Tone + consistency | Customer support, brand voice | Consistent, styled responses |
| Chain-of-Thought | Detailed reasoning | Complex troubleshooting, policy design | Multi-step, defensible recommendations |
***
## Wrap-up and Practical Tips
By completing these exercises you should now be able to:
* Choose the right prompting technique based on goals (speed, format, tone, or reasoning).
* Design explicit constraints (format, length, audience) to get predictable outputs.
* Use One-Shot and Few-Shot prompts to enforce structure and brand voice.
* Use Chain-of-Thought when you need traceable, stepwise reasoning.
Quick checklist before running experiments:
* Provide role/context to the model (e.g., "You are an expert HR advisor").
* Include required sections and constraints.
* Use examples to teach format or tone when needed.
* Keep a simple evaluation rubric (empathy, actionability, timeline) to compare outputs.
Links and References
* [LangChain — Learn with KodeKloud](https://learn.kodekloud.com/user/courses/langchain)
* [General Data Protection Regulation (GDPR)](https://gdpr.eu/)
* [OpenAI API Documentation](https://platform.openai.com/docs)
Recommended next steps:
* Run the provided tasks in your environment and compare outputs across multiple model sizes.
* Iterate on prompts and evaluate with a small rubric (correctness, format, tone).
* Automate comparisons with simple scripts (as shown in task\_5\_comparison.py) to measure improvements over prompt versions.
# Practice Labs Your First AI API Call
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-1/Practice-Labs-Your-First-AI-API-Call/page
Tutorial guiding users through setting up the OpenAI Python client, making chat API calls, extracting responses, and estimating token usage and costs
Let's start with the lab files you'll work through:
```text theme={null}
README.md
task_1_import_setup.py
task_2_client_initialization.py
task_3_api_call_explained.py
task_4_extract_response.py
task_5_tokens_and_costs.py
verify_environment.py
root@controlplane ~/code via ⬢ v3.12.3 ❯
```
In this lesson you'll learn how to make your first AI API calls with the OpenAI Python client. The goal is practical: verify your environment, connect to the API, make a chat completion request, extract the assistant's reply, and inspect token usage and cost — all in progressive steps.
## 1 — Verify the environment
Before writing code, verify that your runtime is ready: activate the virtual environment, confirm Python is available, ensure the OpenAI package is installed, and verify your API keys are present. Run these commands in the lab VM:
```bash theme={null}
source /root/venv/bin/activate
python3 /root/code/verify_environment.py
```
If verification succeeds, the script prints readiness checks and exits. If something fails, re-check your virtual environment and that packages (like the OpenAI Python package) are installed.
Environment variables commonly used in these examples:
| Environment Variable | Purpose |
| -------------------- | -------------------------------------------------------------- |
| OPENAI\_API\_KEY | Your secret API key (keep it private) |
| OPENAI\_API\_BASE | Optional API base URL (use when pointing to a custom endpoint) |
## What is OpenAI?
[OpenAI](https://openai.com) builds ChatGPT and families of large language models (e.g., GPT-4, GPT-4.1 Mini, GPT-3.5). The OpenAI Python client is the bridge between your Python code and the API.
## Task 1 — Import required libraries
Open `task_1_import_setup.py`. You need to import the OpenAI client library and the `os` module to read environment variables. The following file shows the required imports and writes a completion marker for the lab system.
```python theme={null}
#!/usr/bin/env python3
"""
Task 1: Import Required Libraries
Learn what libraries we need for AI API calls.
"""
# Step 1: Import the OpenAI library
# This library helps us talk to AI models
import openai
# Step 2: Import os for environment variables
# This helps us access API keys safely
import os
print("✅ Step 1 Complete: Libraries imported!")
print("- openai: For making API calls")
print("- os: For accessing environment variables")
# Create marker for the automated lab system
os.makedirs("/root/markers", exist_ok=True)
with open("/root/markers/task1_imports_complete.txt", "w") as f:
f.write("SUCCESS")
```
Run it like this:
```bash theme={null}
root@controlplane ~/code via v3.12.3 (venv) ❯ python3 /root/code/task_1_import_setup.py
✅ Step 1 Complete: Libraries imported!
- openai: For making API calls
- os: For accessing environment variables
```
## Authentication and client setup
To authenticate you need:
* OPENAI\_API\_KEY — your secret API key
* OPENAI\_API\_BASE — (optional) custom API base URL
Keep these values out of source control. Use environment variables, a secrets manager, or CI secrets.
## Task 2 — Initialize the OpenAI client
Open `task_2_client_initialization.py` and initialize the OpenAI client using environment variables. This example creates a client object you can reuse across requests.
```python theme={null}
#!/usr/bin/env python3
"""
Task 2: Initialize the OpenAI client
Set up the client using environment variables.
"""
import openai
import os
client = openai.OpenAI(
api_key=os.getenv("OPENAI_API_KEY"),
api_base=os.getenv("OPENAI_API_BASE")
)
print("✅ Step 2 Complete: Connected to OpenAI!")
api_key_preview = os.getenv('OPENAI_API_KEY')[:10] + "..." if os.getenv('OPENAI_API_KEY') else "(not set)"
print(f"- API Key: {api_key_preview}")
print(f"- Base URL: {os.getenv('OPENAI_API_BASE')}")
```
Example run:
```bash theme={null}
root@controlplane ~/code via v3.12.3 (venv) ❯ python3 /root/code/task_2_client_initialization.py
✅ Step 2 Complete: Connected to OpenAI!
- API Key: Sk-kKA1-86...
- Base URL: https://dev.kk-ai-keys.kodekloud.com/v1
```
If client initialization fails, confirm your environment variables are set and that the model you request is available for your account.
## Chat completions — the basics
Chat completions implement conversational interactions. You send an ordered list of messages (with roles) and the model returns assistant messages.
Minimal Python pattern:
```python theme={null}
client.chat.completions.create(
model="openai/gpt-4.1-mini",
messages=[
{"role": "user", "content": "Your question here"}
]
)
```
Roles:
* system — high-level instructions that define behavior
* user — user input
* assistant — model replies
## Task 3 — Make an API call
Open `task_3_api_call_explained.py`. Configure the model and messages, then make a call where the AI introduces itself.
```python theme={null}
#!/usr/bin/env python3
"""
Task 3: Make your first API call
Send a simple user message and print the full response.
"""
import openai
import os
client = openai.OpenAI(
api_key=os.getenv("OPENAI_API_KEY"),
api_base=os.getenv("OPENAI_API_BASE")
)
response = client.chat.completions.create(
model="openai/gpt-4.1-mini",
messages=[
{"role": "user", "content": "Hello AI, please introduce yourself"}
]
)
print("✅ API Call Successful!")
print()
print("🤖 AI said:")
print(response.choices[0].message.content)
print()
print(f"📊 Total tokens used: {response.usage.total_tokens}")
```
Example output:
```bash theme={null}
root@controlplane ~/code via v3.12.3 (venv) ❯ python3 /root/code/task_3_api_call_explained.py
✅ API Call Successful!
🤖 AI said:
Hello! I'm ChatGPT, your AI assistant here to help with a wide range of tasks—from answering questions and providing explanations to creative writing and problem-solving. How can I assist you today?
📊 Total tokens used: 53
```
If you receive PermissionDenied or "model not supported" errors, switch to a model available on your account or check API permissions.
## Task 4 — Extract the AI's response
Responses contain nested structures. The straightforward path to the assistant's reply is:
```text theme={null}
response.choices[0].message.content
```
Open `task_4_extract_response.py` to extract and print that text.
```python theme={null}
#!/usr/bin/env python3
"""
Task 4: Extract the AI's response
Show how to retrieve the assistant's message from the response object.
"""
import openai
import os
client = openai.OpenAI(
api_key=os.getenv("OPENAI_API_KEY"),
api_base=os.getenv("OPENAI_API_BASE")
)
response = client.chat.completions.create(
model="openai/gpt-4.1-mini",
messages=[
{"role": "user", "content": "What is Python in one sentence?"}
]
)
ai_text = response.choices[0].message.content
print("🍬 Successfully extracted the AI's response!")
print("\n" + "="*60)
print("Question: What is Python in one sentence?")
print("\nAI's Answer:")
print(ai_text)
print("="*60)
# Show the golden path
print("\n🔑 THE GOLDEN PATH - Memorize this:")
print("response.choices[0].message.content")
```
Example output:
```bash theme={null}
root@controlplane ~/code via v3.12.3 (venv) ❯ python3 /root/code/task_4_extract_response.py
🍬 Successfully extracted the AI's response!
============================================================
Question: What is Python in one sentence?
AI's Answer:
Python is a high-level, interpreted programming language known for its readability, simplicity, and versatility across various applications.
============================================================
🔑 THE GOLDEN PATH - Memorize this:
response.choices[0].message.content
✅ Task 4 completed! You now know how to extract AI responses!
```
## Tokens and costs
Tokens are the billing and processing unit used by models. Every request consumes tokens from your account:
| Token Type | What it represents | Example |
| ------------------------ | ---------------------------------------- | ---------------------------- |
| prompt/input tokens | Tokens consumed by the input you send | Your question text |
| completion/output tokens | Tokens generated by the model as a reply | The assistant's answer |
| total tokens | Sum of prompt + completion | Billed total for the request |
Output tokens are often priced higher than input tokens, so being concise helps control costs.
Keep your API key secure. Never hard-code it in scripts or check it into version control. Use environment variables or a secrets manager.
## Task 5 — Extract token usage and compute cost
Open `task_5_tokens_and_costs.py`. The response includes a `usage` object with three fields: `prompt_tokens`, `completion_tokens`, and `total_tokens`. Use these values to compute a simple cost estimate with your per-token pricing.
```python theme={null}
#!/usr/bin/env python3
"""
Task 5: Extract token usage and compute cost
Read usage from the response and print a cost breakdown.
"""
import openai
import os
# Example per-token prices (replace with real prices for accurate cost)
INPUT_TOKEN_PRICE = 0.000000789 # example price per input token in dollars
OUTPUT_TOKEN_PRICE = 0.0000023 # example price per output token in dollars
client = openai.OpenAI(
api_key=os.getenv("OPENAI_API_KEY"),
api_base=os.getenv("OPENAI_API_BASE")
)
response = client.chat.completions.create(
model="openai/gpt-4.1-mini",
messages=[
{"role": "user", "content": "Explain what an API is in two sentences."}
]
)
input_tokens = response.usage.prompt_tokens
output_tokens = response.usage.completion_tokens
total_tokens = response.usage.total_tokens
input_cost = input_tokens * INPUT_TOKEN_PRICE
output_cost = output_tokens * OUTPUT_TOKEN_PRICE
total_cost = input_cost + output_cost
print("📊 Token Usage Report:")
print("="*50)
print(f" Your question used: {input_tokens} tokens")
print(f" AI's response used: {output_tokens} tokens")
print(f" Total tokens billed: {total_tokens} tokens")
print("="*50)
print("\n🧾 Cost Breakdown for This Call:")
print(f"Input cost: ${input_cost:.6f} ({input_tokens} tokens)")
print(f"Output cost: ${output_cost:.6f} ({output_tokens} tokens)")
print(f"TOTAL COST: ${total_cost:.6f}")
```
Sample output (varies per request and model):
```bash theme={null}
root@controlplane ~/code via v3.12.3 (venv) ❯ python3 /root/code/task_5_tokens_and_costs.py
📊 Token Usage Report:
==================================================
Your question used: 19 tokens
AI's response used: 301 tokens
Total tokens billed: 320 tokens
==================================================
🧾 Cost Breakdown for This Call:
Input cost: $0.000015 (19 tokens)
Output cost: $0.000693 (301 tokens)
TOTAL COST: $0.000708
```
Be careful with long model responses or high-frequency calls — costs can add up quickly. Use concise prompts, set max tokens when needed, and monitor usage.
## Wrap-up
Congrats — by completing this lab you:
* Verified your environment and runtime
* Initialized the OpenAI Python client
* Made chat completion requests
* Extracted assistant replies via response.choices\[0].message.content
* Read token usage and estimated costs
Next steps: experiment with system messages to control behavior, try longer multi-turn conversations, and test different models to compare quality and cost.
## Quick reference and links
* OpenAI API docs: [https://platform.openai.com/docs](https://platform.openai.com/docs)
* OpenAI homepage: [https://openai.com](https://openai.com)
* LangChain (multi-provider tooling): [https://learn.kodekloud.com/user/courses/langchain](https://learn.kodekloud.com/user/courses/langchain)
Relevant local files in this lab:
| File | Purpose |
| ---------------------------------- | --------------------------------------------- |
| verify\_environment.py | Check Python, venv, and environment variables |
| task\_1\_import\_setup.py | Import libraries and mark completion |
| task\_2\_client\_initialization.py | Initialize the OpenAI client |
| task\_3\_api\_call\_explained.py | Send a simple chat completion |
| task\_4\_extract\_response.py | Extract the assistant message |
| task\_5\_tokens\_and\_costs.py | Read token usage and compute estimated cost |
You're ready to build on this foundation and explore richer prompts, system instructions, and multi-turn dialogues. Good luck!
# Prompt Engineering Techniques
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-1/Prompt-Engineering-Techniques/page
Guide to crafting prompts for TechCorp's AI assistant covering techniques, role and format specification, examples, and best practices to improve output quality and consistency
Prompt engineering is the practice of designing inputs to an AI assistant so the responses are accurate, concise, and formatted for your needs. Here we focus on how to craft prompts for TechCorp’s AI Document Assistant — not how to build LangChain apps — because small prompt changes (scope, role, format) dramatically affect output quality.
Why prompt engineering matters
* Vague prompts force the model to guess intent, leading to longer, noisier, or off-topic responses.
* Adding minimal constraints (audience, region, format) narrows results and improves relevance.
* Explicit roles and format instructions help the assistant maintain consistent tone and structure.
Example of a vague prompt:
```text theme={null}
what is the policy?
```
More specific and actionable:
```text theme={null}
what's the company's remote work policy for international employees?
```
Be explicit about scope, audience, and desired output format. Small additions — like region, role, or format — often produce substantially better answers.
Define role and output format
Telling the model “who it is” and “how to present the answer” controls voice and structure. For example:
```text theme={null}
You are a TechCorp customer support expert. When asked about company policy, always respond with bullet points for readability.
```
This simple role + format instruction reduces ambiguity and yields predictable outputs across multiple prompts.
Prompting techniques overview
Choose the appropriate technique based on how much guidance you provide: zero-shot, one-shot, few-shot, or chain-of-thought.
Zero-shot prompting
Zero-shot asks the model to perform a task without examples. It relies on the model’s internal knowledge and generalization.
Example:
```text theme={null}
Write a data privacy policy for our European customers.
```
One-shot and few-shot prompting
One-shot and few-shot prompts include one or several examples in the prompt to demonstrate the desired output format, tone, or structure. This helps the model pattern-match and produce consistent results.
Workflow example:
* Provide a template or single example of the policy structure.
* Ask the model to “Write a data privacy policy following the same structure.”
Few-shot is similar but supplies multiple samples to cover edge cases and formatting variations.
Chain-of-thought prompting
Chain-of-thought (CoT) prompts ask the model to show or follow intermediate reasoning steps. Instead of only requesting a final output, you specify the stepwise process the assistant should use.
Example steps:
* Review current GDPR requirements for data retention periods.
* Analyze the existing policy to identify gaps.
* Research industry best practices for similar companies.
* Draft specific, implementable recommendations.
Chain-of-thought prompts can improve analytic depth but may increase verbosity and expose intermediate reasoning. In production, avoid revealing sensitive internal reasoning or use post-processing to extract only final action items.
Comparison table: choosing a technique
| Technique | When to use | Strengths | Limitations |
| ---------------- | ---------------------------------------- | ---------------------------------------: | -------------------------------------- |
| Zero-shot | Quick tasks with standard formats | Fast, minimal prep | May be too generic |
| One-shot | You have one clear example/template | Low prep, improved formatting | Limited coverage |
| Few-shot | You can provide multiple examples | Better generalization, covers edge cases | More prompt length |
| Chain-of-thought | Complex reasoning or multi-step analysis | Higher-quality reasoning | Verbose; may reveal intermediate steps |
Actionable prompt template
Use this scaffold to compose consistent, reusable prompts. Replace each bracketed section with your specifics.
```text theme={null}
Role: You are a [role], e.g., "TechCorp policy expert".
Context: [Provide relevant context or background].
Examples: [Optional — paste 1–3 examples or a single template].
Task: [Clear instruction of what to do].
Constraints: [e.g., length, regulations, audience region].
Format: [e.g., bullet points, numbered steps, markdown, JSON].
```
Example using the template:
```text theme={null}
Role: You are a TechCorp legal analyst.
Context: Our European engineering teams process customer IDs and logs.
Examples: See the provided policy template below.
Task: Draft a GDPR-compliant data retention policy focused on logs and temporary IDs.
Constraints: Max 600 words; include retention periods and deletion processes.
Format: Use numbered sections and a short executive summary.
```
Prompt-engineering best practices
* Start with a clear role and targeted context.
* Specify the desired output format (bullets, sections, JSON).
* Supply examples or templates for consistent formatting.
* Limit scope (audience, region, timeframe) to avoid irrelevant detail.
* Test iteratively — refine prompts based on actual outputs.
* Use chain-of-thought only when you need the model’s intermediate reasoning, and sanitize outputs before exposing them.
Examples: bad vs. improved prompts
* Bad: what is the policy?
* Improved: You are a TechCorp HR expert. Summarize the remote-work policy for international employees in 5 bullet points, highlighting eligibility, timezone expectations, and tax considerations.
References and further reading
* [LangChain — KodeKloud course](https://learn.kodekloud.com/user/courses/langchain)
* [OpenAI Prompting Guide](https://platform.openai.com/docs/guides/completion/prompt-design)
* [Retrieval-Augmented Generation (RAG) overview](https://en.wikipedia.org/wiki/Retrieval-augmented_generation)
Putting it together
Prompt engineering is selecting the right method (zero-/one-/few-shot, or chain-of-thought) and composing a prompt with clear role, context, examples, and format. Thoughtful prompts act like precise instructions for the agent, improving relevance, consistency, and usefulness of the assistant’s responses.
# Conclusion
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-2/Conclusion/page
Blueprint for building a context-aware document search agent using RAG, vector databases, orchestration, model management, and prompt engineering to improve enterprise knowledge access
In this lesson we combined context windows, vector databases, orchestration layers, model management practices, and prompt engineering to build a practical, context-aware document search agent for TechCorp. The architecture demonstrates how retrieval-augmented generation (RAG) and semantic vector search convert slow, manual lookups into fast, accurate, context-rich answers—transforming knowledge access across the organization.
Key outcomes at a glance:
| Benefit | Practical impact | Notes for implementation |
| ------------------------ | ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| Performance & accuracy | Queries that previously took \~30 minutes now return relevant answers in under 30 seconds | Use semantic embeddings, nearest-neighbor search in a vector DB, and RAG to surface and synthesize evidence for answers |
| User experience | Chat-style UI preserves conversation state and supports follow-ups without repeated context | Keep short-term and long-term context windows and display provenance for trust |
| Operational availability | 24/7 assistance while the application is running, across time zones and shifts | Automate health checks, autoscaling, and graceful degradation in orchestration layers |
| Extendability | Foundation for predictive analytics, proactive compliance agents, and workflow automation | Expose modular APIs and pipelines so new capabilities can be plugged into the system |
Practical next steps: ensure data governance (access controls and redaction), implement monitoring and evaluation for relevance and hallucination, set up model versioning and cost monitoring in your model management platform (MCP), and iterate on prompts and retrieval strategies based on user feedback.
Moving from static repositories to living, intelligent systems is a turning point for enterprise knowledge management. With the right engineering patterns—vector stores for retrieval, LLMs for understanding and synthesis, orchestration layers for reliability, and an MCP for governance and observability—you can build applications that not only answer questions but increasingly anticipate and resolve business problems.
Recommended next actions
* Establish data governance: role-based access, redaction, and encrypted storage for sensitive documents.
* Monitor model outputs: log provenance, measure relevance, and detect hallucinations with automated tests.
* Version and cost control: track model versions, deployments, and runtime costs in your MCP.
* Iterate on retrieval and prompts: A/B test retrieval strategies, embedding models, and prompt templates based on user metrics.
Links and references
* [Retrieval-augmented Generation (RAG) overview](https://www.deepset.ai/guides/rag)
* [LangChain documentation](https://langchain.readthedocs.io/)
* [Vector databases: Pinecone](https://www.pinecone.io/), [Milvus](https://milvus.io/)
* [Best practices in prompt engineering](https://www.promptingguide.ai/)
* [Model management and MLOps patterns](https://ml-ops.org/)
The approach outlined here is a practical blueprint for TechCorp and similar organizations that want to unlock knowledge at scale—reducing time-to-answer, improving accuracy, and enabling proactive automation that adds real business value.
# LangGraph for AI Workflows
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-2/LangGraph-for-AI-Workflows/page
Describes LangGraph extending LangChain to orchestrate stateful, multi-node AI workflows with conditional branching, loops, shared typed state, and reusable nodes for complex tasks like compliance analysis
[LangChain](https://langchain.com) is excellent for linear chains and simple pipelines. However, when business requirements demand multi-step workflows, conditional branching, iterative processing, or persistent context, you need more advanced orchestration. LangGraph extends LangChain to handle stateful, multi-node workflows that go beyond single-turn Q\&A.
Overview
* LangGraph models complex workflows as a graph of nodes (units of computation) connected by edges (execution flow).
* Each node encapsulates a specific responsibility (search, extraction, evaluation, reporting, etc.).
* Edges can be conditional, enabling branching and loops.
* A shared, persistent state (state graph) is accessible to all nodes, allowing context to carry across the entire workflow.
Example scenario
A customer asks: "I need to understand our data privacy policy for EU customers."\
Assume TechCorp has a 500GB data store that contains EU-specific policy documents. The system must locate relevant documents, extract the content, evaluate GDPR compliance, cross-reference local regulations, and produce an actionable report.
Typical LangGraph node workflow for this compliance task:
1. Search and gather privacy policy documents.
2. Extract and clean document content.
3. Evaluate GDPR compliance with an LLM.
4. Cross-reference local EU regulations.
5. Identify compliance gaps and generate recommendations.
A node is a callable task. Edges determine where execution flows next and can include conditional checks. For example:
* After Node 1 gathers documents, the edge routes to Node 2 for extraction.
* After Node 3 evaluates compliance, a conditional edge can route to Node 4 for deeper analysis or directly to Node 5 for reporting.
Shared state
LangGraph supports a typed, persistent state shared across nodes. This allows nodes to read and update workflow context (e.g., list of documents, current document, analysis results).
Typed shared state example
The following Python TypedDict demonstrates a concrete state shape used across the workflow:
```python theme={null}
from typing import List, Optional
from typing_extensions import TypedDict
class ComplianceState(TypedDict):
topic: str
documents: List[str]
current_document: Optional[str]
compliance_score: Optional[int]
gaps: List[str]
recommendations: List[str]
```
How the state flows through nodes:
* Node 1 (search) populates `documents` with found policy files.
* Node 2 (extract) iterates documents and sets `current_document`.
* Node 3 (evaluate) computes `compliance_score`.
* Node 4 (cross-reference) identifies `gaps`.
* Node 5 (report) appends `recommendations`.
Conditional routing and loops
Using the shared state, the graph can adapt execution dynamically:
* If Node 3 sets `compliance_score` below 75%, a conditional edge can loop back to Node 1 to gather more documents (iterative analysis).
* If the score exceeds 75%, the flow can proceed directly to Node 5 to generate the final report.
Common orchestration patterns enabled by LangGraph:
| Pattern | Description | Use case |
| --------------------- | ---------------------------------------------------------- | --------------------------------------------------------------------- |
| Iterative loops | Re-run parts of the graph until a condition is satisfied | Aggregate more documents until confidence threshold reached |
| Conditional branching | Route to different subgraphs based on intermediate results | Different analysis for EU vs non-EU regulations |
| Persistent context | Maintain a shared state accessible to all nodes | Carry findings, intermediate scores, and metadata across the workflow |
| Parallel branches | Execute independent nodes concurrently and merge results | Run multiple evaluation heuristics and combine outputs |
Benefits for the TechCorp compliance assistant
* Declarative modeling of complex workflows (no monolithic scripts).
* Clear separation of concerns (each node focuses on a single responsibility).
* Reusable nodes and conditional edges for flexible behavior.
* Persistent typed state for robust, type-safe orchestration.
Lab: hands-on LangGraph exercises
The course provides lab files to build and run a complete research assistant workflow demonstrating nodes, edges, conditional routing, and shared state.
| File | Purpose | Notes |
| ---------------------------------- | ----------------------------------------- | ----------------------------------------- |
| task\_1\_understanding\_imports.py | Explore required imports and dependencies | Verify correct SDKs and LLM clients |
| task\_2\_creating\_nodes.py | Define node implementations | Implement search, extract, evaluate nodes |
| task\_3\_connecting\_edges.py | Wire nodes together with edges | Add conditional logic for branches |
| task\_4\_complete\_flow\.py | Combine nodes into a runnable graph | End-to-end integration |
| task\_5\_conditional\_routing.py | Implement and test conditional edges | Threshold logic and branching |
| task\_6\_calculator\_tool.py | Small utility node/tool example | Demonstrates tool integration |
| task\_7\_research\_agent.py | Build the final research assistant agent | Orchestrates the complete workflow |
| verify\_environment.py | Environment checks and prerequisites | Run before labs to confirm setup |
Run verify\_environment.py first to confirm your Python version, required packages, and API keys are configured. This prevents common runtime errors during the labs.
Further reading and references
* [LangChain](https://langchain.com) — Core abstractions for chains and agents.
* Retrieval-Augmented Generation (RAG) — pattern for combining LLMs with external data sources.
* GDPR overview — [https://gdpr.eu/](https://gdpr.eu/) for regulation context when building compliance workflows.
By the end of these labs, you'll have a production-like research assistant that demonstrates how LangGraph orchestrates complex, stateful AI workflows with conditional routing and persistent shared state.
# Model Context Protocol
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-2/Model-Context-Protocol/page
Describes the Model-Context-Protocol for letting AI agents call registered service endpoints with typed schemas to integrate external systems without custom code
Model-Context-Protocol (MCP) rethinks how AI agents integrate with external systems. Instead of having developers write bespoke API integrations for every use case, MCP lets services register as callable tools that agents can invoke. This shifts the integration burden from application code to the agent, enabling more flexible, composable workflows.
In practice, an MCP server exposes one or more well-defined functions (endpoints) with explicit input and output schemas. When an agent runs, it discovers and calls these functions to query or mutate external state. That makes it straightforward to extend an assistant’s capabilities—plug in an MCP server for a system and the agent can use it without additional glue code.
For example, a TechDocs assistant could query customer, order, inventory, or ticketing systems via MCP endpoints. If a user asks, "What's the status of order 1234?", the agent can call an MCP that queries the order-management system, receive the structured response, and compose a natural-language reply that includes the order state.
## Minimal FastAPI MCP server example
Below is a concise, practical example: a FastAPI-based MCP that exposes a simple customer lookup function. It demonstrates the typical pieces of an MCP server:
* A web app that exposes a function endpoint the agent can call.
* Typed request/response models so agents know how to call the function.
* A persistence layer (here, an in-memory dict) — replace with your production DB.
Use this as a template for a real integration (SQL, MongoDB, or any service).
```python theme={null}
# server.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional, Dict
app = FastAPI(title="customer-db-mcp", version="0.1.0")
# Request schema: what the MCP client (the AI agent) will send
class GetCustomerRequest(BaseModel):
customer_id: str
# Response schema: what the MCP server returns
class Customer(BaseModel):
customer_id: str
name: str
email: Optional[str] = None
status: str # e.g., 'shipped', 'processing', 'closed' (use values appropriate for your domain)
# Fake in-memory database (replace with real DB in production)
customers: Dict[str, Customer] = {
"1234": Customer(customer_id="1234", name="Alice Johnson", email="alice@example.com", status="shipped"),
"2345": Customer(customer_id="2345", name="Bob Smith", email="bob@example.com", status="processing"),
}
@app.post("/mcp/get_customer", response_model=Customer)
async def get_customer(req: GetCustomerRequest):
"""
MCP function: returns customer information by customer_id.
The agent can call this endpoint to retrieve customer state.
"""
cust = customers.get(req.customer_id)
if not cust:
raise HTTPException(status_code=404, detail="customer not found")
return cust
```
Run the server with uvicorn:
```bash theme={null}
uvicorn server:app --host 0.0.0.0 --port 8000 --reload
```
Example MCP client request (what an agent or other client would send):
```bash theme={null}
curl -X POST "http://localhost:8000/mcp/get_customer" \
-H "Content-Type: application/json" \
-d '{"customer_id": "1234"}'
```
Example JSON response:
```json theme={null}
{
"customer_id": "1234",
"name": "Alice Johnson",
"email": "alice@example.com",
"status": "shipped"
}
```
## Key components and best practices
| Component | Purpose | Example / Notes |
| --------------------------- | --------------------------------------- | ------------------------------------ |
| Endpoint (function surface) | Defines callable operations for agents | POST /mcp/get\_customer |
| Typed schemas | Makes discovery and validation reliable | Pydantic models, OpenAPI schemas |
| Persistence | Store and retrieve real-world state | SQL, MongoDB, managed services |
| Security | Protect data and control access | API keys, OAuth, RBAC, rate limits |
| Agent discovery | How agents find and interpret functions | OpenAPI, function registry, metadata |
This structure—define endpoints and schemas once—lets any compatible agent call your MCP server to fetch or modify external state. Many ecosystems publish reusable MCP adapters for common services (e.g., source control, databases, productivity tools), letting you plug them into agents without custom integration work.
MCP servers should clearly define input and output schemas (e.g., via [OpenAPI](https://www.openapis.org) / [Pydantic](https://docs.pydantic.dev)). This makes it easy for agents to discover and call them reliably. In production, secure these endpoints (authentication, authorization, rate-limiting) before exposing them to agents.
## Links and references
* FastAPI: [https://fastapi.tiangolo.com](https://fastapi.tiangolo.com)
* uvicorn: [https://www.uvicorn.org](https://www.uvicorn.org)
* Pydantic: [https://docs.pydantic.dev](https://docs.pydantic.dev)
* OpenAPI: [https://www.openapis.org](https://www.openapis.org)
* SQL: [https://en.wikipedia.org/wiki/SQL](https://en.wikipedia.org/wiki/SQL)
* MongoDB: [https://www.mongodb.com](https://www.mongodb.com)
* Example repositories and community MCP adapters: search GitHub for "MCP" and "agent tooling" for community-provided integrations
Use this pattern to make your AI assistants actionable: define function surfaces, provide strict schemas, and secure endpoints—then let the agent do the integration work.
# Practice Labs Advanced MCP Concepts
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-2/Practice-Labs-Advanced-MCP-Concepts/page
Guide to using MCP with LangGraph to expose and integrate external tools and multi-server orchestration for agents, including setup, calculator server, tool schemas, and examples.
We go deeper into MCP (Model Context Protocol) and demonstrate how to extend LangGraph agents with external tools. MCP acts like a universal port (think USB) that standardizes how AI systems connect to tools, databases, and APIs. With MCP, LangGraph agents can call out to external services and receive structured responses.
This lesson covers:
* Environment setup for the lab
* Conceptual MCP architecture and how it maps to agents
* Task 1: Run a simple MCP server (Calculator)
* Task 2: Connect an agent to MCP tools
* Task 3: Orchestrate multiple MCP servers and aggregate tools
* Next steps and references
***
## Environment — create the virtual environment and install dependencies
Create or activate your virtual environment, then install the required packages: LangGraph (workflow framework), LangChain (core model abstractions), and the MCP adapters for model integration and servers.
Environment setup (bash)
```bash theme={null}
cd /root && source /root/venv/bin/activate
pip install langgraph langchain langchain-openai langchain-mcp-adapters
```
You may see dependency messages during installation similar to:
```text theme={null}
Requirement already satisfied: sse-starlette>=1.6.1 in ./venv/lib/python3.12/site-packages (from mcp>=1.9.2->langchain-mcp-adapters) (3.0.2)
Requirement already satisfied: starlette>=0.27 in ./venv/lib/python3.12/site-packages (from mcp>=1.9.2->langchain-mcp-adapters) (0.48.0)
Requirement already satisfied: uvicorn>=0.31.1 in ./venv/lib/python3.12/site-packages (from mcp>=1.9.2->langchain-mcp-adapters) (0.37.0)
Requirement already satisfied: attrs>=22.2.0 in ./venv/lib/python3.12/site-packages (from jsonschema>=4.20.0->mcp>=1.9.2->langchain-mcp-adapters) (25.4.0)
Requirement already satisfied: jsonschema-specifications>=2023.03.6 in ./venv/lib/python3.12/site-packages (from jsonschema>=4.20.0->mcp>=1.9.2->langchain-mcp-adapters) (2025.9.1)
Requirement already satisfied: referencing>=0.28.4 in ./venv/lib/python3.12/site-packages (from jsonschema>=4.20.0->mcp>=1.9.2->langchain-mcp-adapters) (0.36.2)
Requirement already satisfied: rpds-py>=0.7.1 in ./venv/lib/python3.12/site-packages (from jsonschema>=4.20.0->mcp>=1.9.2->langchain-mcp-adapters) (0.27.1)
Requirement already satisfied: python-dotenv>=0.21.0 in ./venv/lib/python3.12/site-packages (from pydantic-settings>=2.5.2->mcp>=1.9.2->langchain-mcp-adapters) (1.1.1)
```
Run the verification script:
```bash theme={null}
python3 /root/code/task_1_mcp_basics.py
```
***
## MCP architecture — conceptual overview
MCP bridges an AI assistant built with LangGraph to external tools and services. The high-level flow:
* The MCP server registers tools and publishes their schemas.
* A client connects to the server and fetches tool definitions.
* A LangGraph (or LangChain-style) agent receives those tools and decides when to call them.
* When invoked, the MCP client routes the tool call to the server and returns a structured response.
Analogy: MCP is the USB port — the protocol is the port, the server is a device, and tools are the device's functions. LangGraph is the host computer using those functions.
Key MCP concepts at a glance:
| Concept | Purpose | Notes |
| ------------ | ------------------------------------- | ---------------------------------------------------------- |
| MCP Server | Hosts tools and exposes their schemas | Tools annotated with type hints produce structured schemas |
| MCP Client | Discovers and calls tools | client.get\_tools() returns tools for the agent |
| Agent | Uses tools to extend capabilities | create\_react\_agent(model, tools) builds the agent |
| Transports | How server and client communicate | stdin/stdout, SSE, HTTP supported |
| Multi-server | Aggregate tools across servers | Use multi-server clients to merge toolsets |
***
## Task 1 — MCP basics: build a Calculator server
Create a simple MCP server named "Calculator" that exposes calculator tools (add, multiply). Servers can be run using stdin/stdout transport for local testing or via SSE/HTTP for networked deployments.
Example server script (completed):
```python theme={null}
# Initialize the MCP server
mcp = FastMCP("Calculator")
# Create calculator tools using FastMCP decorators
@mcp.tool()
def add(a: float, b: float) -> float:
"""Add two numbers together"""
result = a + b
print(f"🔧 Tool 'add' called with a={a}, b={b}")
print(f"➕ Result: {result}")
return result
# Create the multiply tool
@mcp.tool()
def multiply(a: float, b: float) -> float:
"""Multiply two numbers"""
result = a * b
print(f"🔧 Tool 'multiply' called with a={a}, b={b}")
print(f"✖ Result: {result}")
return result
```
Tips for tool implementations:
* Use Python type hints for parameters and return types; they generate structured schemas consumed by clients.
* Keep logs inside tools for easier debugging (print statements or structured logging).
* Choose the appropriate transport: stdin/stdout is easiest for local tests; SSE/HTTP is suitable for distributed clients.
Expected console output when the server starts (illustrative):
```text theme={null}
✅ Task 1 complete! MCP tools tested successfully.
------------------------------------------------------------
🚀 STARTING MCP SERVER
------------------------------------------------------------
The calculator MCP server is now starting...
Keep this terminal open - the server will run continuously.
Use Ctrl-C to stop the server when you're done.
Server ready! Waiting for client connections...
```
Keep the server terminal open while clients connect. If you stop the server, the agent will no longer be able to reach the tools.
***
## Task 2 — Integrate MCP tools with a LangGraph agent
Connect the Calculator server to a LangGraph (or LangChain-style) agent. The client obtains tools via client.get\_tools(), and the agent is created with those tools so it can choose when to call them (for example, using a ReAct-style agent).
Example async integration (completed):
```python theme={null}
async def run_agent_with_mcp():
"""Create and run agent with MCP tools"""
# Get tools from MCP client
tools = await client.get_tools()
# Create react agent with model and tools
agent = create_react_agent(model, tools)
print("✅ Agent created with MCP tools!\n")
print("=" * 60)
print("TESTING MCP-INTEGRATED AGENT:")
print("=" * 60)
# Test 1: Math query (should use MCP tools)
print("\nTest 1: Math Query")
math_response = await agent.ainvoke({
"messages": "What is 25 plus 17?"
})
print(f"Response: {math_response['messages'][-1].content}")
```
Representative debug output:
```text theme={null}
Processing request of type ListToolsRequest
Processing request of type CallToolRequest
Response: 25 plus 17 is 42.
Test 2: Non-math Query
Response: The capital of France is Paris.
```
Notes:
* The agent uses tool schemas to decide whether invoking a tool is appropriate.
* Non-math queries that require general knowledge should be handled by the model directly without tool calls.
***
## Task 3 — Multi-server orchestration (Calculator + Weather)
Scale the system by connecting multiple MCP servers (for example, Calculator and Weather). A MultiServerMCPClient or equivalent gathers tools from all servers; the agent is then built with the aggregated toolset so it can route requests to the right service.
Example multi-server orchestration (cleaned and completed):
```python theme={null}
async def run_multi_server_agent():
"""Create and run agent with tools from multiple MCP servers"""
print("📦 Loading tools from multiple servers...")
# Get all tools from both servers
tools = await client.get_tools()
print(f"✅ Loaded {len(tools) if hasattr(tools, '__len__') else 'multiple'} tools from servers")
# Create react agent with model and tools
agent = create_react_agent(model, tools)
print("\n" + "-" * 60)
print("TESTING MULTI-SERVER ORCHESTRATION:")
print("=" * 60)
# Example queries
print("\nTest 1: Calculator query")
calc_response = await agent.ainvoke({"messages": "What is 8 times 9?"})
print(f"Response: {calc_response['messages'][-1].content}")
print("\nTest 2: Weather comparison query")
weather_response = await agent.ainvoke({
"messages": "Compare current weather in New York and Tokyo."
})
print(f"Response: {weather_response['messages'][-1].content}")
```
Representative outputs when multiple servers are used:
```text theme={null}
Processing request of type ListToolsRequest
Processing request of type CallToolRequest
Response: 8 times 9 is 72.
Processing request of type CallToolRequest
Processing request of type ListToolsRequest
Response: The current weather comparison between New York and Tokyo is as follows:
New York:
- Temperature: 17°C
- Condition: Clear
- Humidity: 58%
- Wind: 14 km/h
Tokyo:
- Temperature: 18°C
- Condition: Clear
- Humidity: 51%
- Wind: 16 km/h
Both cities have clear weather with similar temperatures, but New York has slightly higher humidity while Tokyo has a bit stronger wind.
```
Best practices for multi-server setups:
* Use a consistent naming convention (for example, prefix tools with the server name) so tools from different servers do not collide.
* Monitor ListToolsRequest and CallToolRequest logs to trace cross-server calls.
* Start with read-only tools when exposing external systems (APIs, DBs) and gradually add write capabilities with proper access control.
***
## Deeper explorations and next steps
Once you are comfortable with MCP basics and multi-server orchestration, extend MCP to expose:
* Databases (query/update operations)
* External REST APIs (wrapped as typed tools)
* File systems (search, read, write)
* Human-in-the-loop endpoints (approval workflows)
The pattern stays the same:
1. Expose structured tools on an MCP server.
2. Fetch tools from the client (client.get\_tools()).
3. Build an agent (create\_react\_agent or similar) that orchestrates tool calls as needed.
Key reminders:
| Topic | Recommendation |
| ------------- | ---------------------------------------------------------------------- |
| Tool schemas | Use type hints for strong, machine-readable schemas |
| Transports | Start with stdin/stdout for local tests; use HTTP/SSE for production |
| Security | Protect write operations and external integrations with authentication |
| Observability | Log ListToolsRequest and CallToolRequest for troubleshooting |
This concludes the lesson. Experiment with exposing new resources and creating safe, auditable human-in-the-loop flows.
***
## Links and references
* [LangChain course (overview)](https://learn.kodekloud.com/user/courses/langchain)
* LangGraph documentation (refer to your project docs or README for LangGraph usage)
* MCP adapters (installed via pip as part of this lab)
Happy experimenting — extend your agents with real-world services using MCP and LangGraph.
# Practice Labs Build Semantic Search Engine
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-2/Practice-Labs-Build-Semantic-Search-Engine/page
Guide to building a production-ready semantic search engine using embeddings, document chunking, ChromaDB and LangChain, with examples for embedding creation, indexing, and similarity search.
We're going to build a semantic search engine step-by-step.
The story begins with TechDocs, Inc., where users search through documentation 10,000 times a day. More than half of those searches fail because traditional keyword search can't connect related phrases like "reset password" and "password recovery."
Our mission is to fix that by building a search system that understands meaning, not just words.
## Approach overview
We’ll build a production-grade semantic search pipeline by following these core steps:
* Convert text (documents and queries) into vector embeddings using an embedding model (sentence-transformers / Hugging Face).
* Store embeddings in a fast vector database (ChromaDB) for nearest-neighbor search.
* For each query, find nearby document embeddings (semantic similarity) and retrieve the top-K chunks.
* Rank and return the most relevant document chunks to the user.
This approach enables queries like "forgot my password" to match documents titled "Password recovery" or "Login help" even when keywords differ.
## Environment setup
Install the packages used for embeddings, orchestration, and vector storage:
* sentence-transformers — embedding models (e.g. all-MiniLM-L6-v2)
* LangChain — orchestration utilities & text splitters
* langchain-community & langchain-huggingface — community integrations for LangChain
* ChromaDB — vector database
* numpy, tempfile, and other utilities
Example environment setup (bash):
```bash theme={null}
# Create and activate a virtual environment
cd /root
python3 -m venv venv
source venv/bin/activate
# Install required packages
pip install sentence-transformers langchain langchain-community langchain-huggingface chromadb numpy
```
After installing dependencies, run the provided verification script to confirm everything is working:
```bash theme={null}
python3 /root/code/verify_environment.py
```
A successful verification prints messages confirming LangChain ↔ ChromaDB integration and basic vector similarity checks, for example:
```text theme={null}
LangChain-ChromaDB integration working
OpenAI configuration found
API Base: https://dev.kk-ai-keys.kodekloud.com/v1
Testing vector similarity operations...
Vector similarity test:
Similar docs similarity: 0.640
Different docs similarity: 0.132
Vector operations working correctly
All environment checks passed!
Your vector database lab environment is fully ready.
Environment Status: PERFECT
Results saved to: /root/markers/environment_verified.txt
```
## Understanding embeddings
Embeddings are the backbone of semantic search. Rather than working with individual keywords, embeddings convert text into dense numerical vectors where semantically similar texts are close in vector space. That enables the search engine to connect queries and documents that use different words but share meaning.
### Quick embedding example (Task 1)
This concise example demonstrates loading a sentence-transformers model, encoding a query and several documents, computing cosine similarity, and printing results. Normalizing embeddings (normalize\_embeddings=True) can improve cosine-similarity stability.
```python theme={null}
# task_1_understanding_embeddings.py
from sentence_transformers import SentenceTransformer, util
import os
def main():
model = SentenceTransformer("all-MiniLM-L6-v2")
query = "forgot my password"
docs = [
"Password recovery: Use the 'Reset Password' link on login page",
"Vacation policy: Request time off 2 weeks in advance",
"Account security: Enable two-factor authentication",
"Login help: Contact IT if you cannot access your account"
]
# Encode query and documents
query_emb = model.encode(query, convert_to_tensor=True)
doc_embs = model.encode(docs, convert_to_tensor=True)
# Compute cosine similarity scores
scores = util.cos_sim(query_emb, doc_embs)[0]
print(f"Query: '{query}'\n")
print("Results (score > 0.3 = relevant):")
for doc, score in zip(docs, scores):
marker = "✅" if score.item() > 0.3 else " "
print(f"{marker} [{score.item():.2f}] {doc}")
print("\n🔎 Notice: Found 'Password recovery' and 'Login help'")
print(" Even though the query didn't contain those exact words!")
os.makedirs("/root/markers", exist_ok=True)
open("/root/markers/task1_embeddings_complete.txt", "w").write("DONE")
if __name__ == "__main__":
main()
```
Example output (abridged):
```text theme={null}
Query: 'forgot my password'
Results (score > 0.3 = relevant):
✅ [0.56] Password recovery: Use the 'Reset Password' link on login page
[0.07] Vacation policy: Request time off 2 weeks in advance
✅ [0.31] Account security: Enable two-factor authentication
✅ [0.60] Login help: Contact IT if you cannot access your account
🔎 Notice: Found 'Password recovery' and 'Login help'
Even though the query didn't contain those exact words!
```
## Document chunking
Large documents should be split into smaller chunks for embedding for two reasons:
* Embedding models have context limits; extremely long texts can be truncated or produce noisy embeddings.
* Smaller, focused chunks preserve local context and improve retrieval accuracy.
However, naive splitting may cut sentences and lose meaning. Use overlapping chunks to preserve sentence continuity at boundaries. A common starting point is \~500 characters per chunk with \~100-character overlap; tune this for your documents and model.
Example using LangChain's RecursiveCharacterTextSplitter:
```python theme={null}
# task_2_chunking.py
from langchain.text_splitter import RecursiveCharacterTextSplitter
def chunk_document(text, chunk_size=500, chunk_overlap=100):
splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size,
chunk_overlap=chunk_overlap,
separators=["\n\n", "\n", " ", ""]
)
return splitter.split_text(text)
if __name__ == "__main__":
long_text = "..." # replace with actual document text
chunks = chunk_document(long_text)
for i, chunk in enumerate(chunks, start=1):
print(f"📄 Chunk {i} ({len(chunk)} chars):\n{chunk[:200]}...\n")
print("✅ Task 2 completed! Document chunking mastered.")
```
• Preserves sentence boundaries\
• Maintains context with overlap\
• Optimizes chunks for embedding models\
• Can improve retrieval accuracy significantly
## Vector stores (ChromaDB)
Embeddings are vectors; we need a vector store to index and search them efficiently. ChromaDB is a production-ready vector database that supports fast similarity search and metadata filtering. LangChain integrates with ChromaDB to simplify storing and querying embeddings.
How vector search works (high-level):
1. Document → embed → store in DB
2. Query → embed → find similar embeddings
3. Return top-K results ranked by cosine similarity
### Create a Chroma vector store and index documents (Task 3)
This example shows how to initialize HuggingFace embeddings via LangChain, create Document objects, and build a Chroma vector store in a persistent temporary directory.
```python theme={null}
# task_3_build_vectorstore.py
from langchain_community.vectorstores import Chroma
from langchain_huggingface import HuggingFaceEmbeddings
from langchain.schema import Document
import tempfile
import os
def build_vectorstore(doc_texts):
# Initialize embeddings (HuggingFace wrapper)
embeddings = HuggingFaceEmbeddings(
model_name="all-MiniLM-L6-v2",
model_kwargs={"device": "cpu"},
encode_kwargs={"normalize_embeddings": True}
)
# Create Document objects (optional metadata can be added)
documents = [Document(page_content=text) for text in doc_texts]
# Persist vector store to a directory (use mkdtemp so the directory remains available
# after this function returns; TemporaryDirectory would be removed on exit)
temp_dir = tempfile.mkdtemp()
vectorstore = Chroma.from_documents(
documents=documents,
embedding=embeddings,
persist_directory=temp_dir
)
# Ensure data is persisted to disk if the vectorstore supports it
try:
vectorstore.persist()
except Exception:
# Some vectorstore wrappers persist automatically; ignore if not applicable
pass
print(f"📚 Loaded {len(documents)} documents into vector store at {temp_dir}...")
return vectorstore
if __name__ == "__main__":
sample_docs = [
"Remote work policy allows employees to work from home up to 3 days per week with manager approval.",
"Work hours are flexible but core hours 10 AM to 3 PM are required.",
"Health insurance covers employee and dependents with company paying 80% of premiums.",
]
vs = build_vectorstore(sample_docs)
print("✅ Vector store ready!")
```
## Semantic search — Bringing it all together
Now implement the search pipeline: convert the user query to an embedding, query the ChromaDB vector store for the top-K similar chunks, optionally filter by a score threshold, and return the best results.
### Full search example (Task 4)
This example assumes you have a built `vectorstore` (as in Task 3). It shows how to run a similarity search, obtain scores, apply a threshold, and print filtered results.
```python theme={null}
# task_4_semantic_search.py
import tempfile
from langchain_community.vectorstores import Chroma
from langchain_huggingface import HuggingFaceEmbeddings
from langchain.schema import Document
def build_search_engine(knowledge_base):
# Initialize embeddings and documents
embeddings = HuggingFaceEmbeddings(
model_name="all-MiniLM-L6-v2",
model_kwargs={"device": "cpu"},
encode_kwargs={"normalize_embeddings": True}
)
documents = [Document(page_content=text) for text in knowledge_base]
# Create vector store in a temporary directory (searching is performed while directory exists)
with tempfile.TemporaryDirectory() as temp_dir:
vectorstore = Chroma.from_documents(
documents=documents,
embedding=embeddings,
persist_directory=temp_dir
)
print("✅ Vector store ready!\n")
# Search configuration
search_query = "work from home policy"
k = 3
score_threshold = 0.5
print(f"● Searching for: '{search_query}'")
print(f"Returning top {k} results")
print("-" * 28)
# Basic similarity search (returns Documents)
results = vectorstore.similarity_search(search_query, k=k)
print("\n📚 Search Results:\n")
for i, doc in enumerate(results, 1):
print(f"{i}. {doc.page_content}\n")
# Search with scores (returns list of (Document, score))
# Note: when embeddings are normalized and the vector store returns cosine similarity,
# higher scores indicate more similar results.
results_with_scores = vectorstore.similarity_search_with_score(search_query, k=5)
relevant_results = [(doc, score) for doc, score in results_with_scores if score >= score_threshold]
print(f"\n🔎 Filtered Search (threshold > {score_threshold}):")
print("-" * 40)
if relevant_results:
for i, (doc, score) in enumerate(relevant_results, 1):
print(f"{i}. [{score:.2f}] {doc.page_content}\n")
else:
print("No results above the score threshold.")
if __name__ == "__main__":
knowledge_base = [
"Remote work policy allows employees to work from home up to 3 days per week with manager approval.",
"Work hours are flexible but core hours 10 AM to 3 PM are required.",
"Health insurance covers employee and dependents with company paying 80% of premiums.",
# ... additional docs ...
]
build_search_engine(knowledge_base)
```
Simulated example run summary:
```text theme={null}
Task 4: Semantic Search Implementation
=====================================
✅ Loading 12 documents into vector store...
✔ Vector store ready!
● Searching for: 'work from home policy'
Returning top 3 results
----------------------------
📚 Search Results:
1. Remote work policy allows employees to work from home up to 3 days per week with manager approval.
2. Work hours are flexible but core hours 10 AM to 3 PM are required.
3. Health insurance covers employee and dependents with company paying 80% of premiums.
🔎 Filtered Search (threshold > 0.5):
```
## Recap & next steps
In this lab we:
* Set up an environment for embeddings and vector search.
* Learned how embeddings capture semantic similarity beyond keywords.
* Implemented smart, overlapping document chunking.
* Built a ChromaDB-backed vector store and indexed document chunks.
* Implemented a semantic search pipeline that converts queries to embeddings, performs similarity search, and returns ranked, filtered results.
Next experiments to improve relevance and production-readiness:
* Try different embedding models (speed vs. accuracy tradeoffs).
* Tune chunk sizes and overlap parameters based on document structure.
* Persist vector stores to a stable location and design a scalable deployment.
* Add metadata filtering (document type, last-updated) and combine with a ranker or reranker for hybrid retrieval.
Next steps: experiment with model variants, tune chunking/thresholds, and add metadata filters (e.g., document type, last-updated) to further improve relevance.
## Tools & resources
| Resource | Use case | Link |
| ------------------------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| sentence-transformers | Fast, high-quality embedding models such as all-MiniLM-L6-v2 | [https://www.sbert.net/](https://www.sbert.net/) |
| LangChain | Orchestration utilities, text splitters, integration helpers | [https://python.langchain.com/](https://python.langchain.com/) |
| langchain-community / langchain-huggingface | Community embeddings / HuggingFace integration for LangChain | [https://github.com/langchain-community/langchain-community-extras](https://github.com/langchain-community/langchain-community-extras) |
| ChromaDB | Vector database for fast similarity search | [https://www.trychroma.com/](https://www.trychroma.com/) |
| Hugging Face models | Additional embedding models to test | [https://huggingface.co/](https://huggingface.co/) |
| NumPy | Numeric utilities and array support | [https://numpy.org/](https://numpy.org/) |
Further reading:
* [Kubernetes Basics](https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/) (for deploying scalable services)
* [LangChain Documentation](https://python.langchain.com/)
* [ChromaDB Docs](https://www.trychroma.com/docs)
Happy building — with embeddings, you can transform keyword-limited search into meaning-aware discovery.
# Practice Labs Build Stateful AI Workflows
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-2/Practice-Labs-Build-Stateful-AI-Workflows/page
Guide to building stateful AI workflows using LangGraph including nodes, routers, tool integrations and a research agent example
This guide walks through building stateful AI workflows using LangGraph and related tools. You'll set up a Python environment, create nodes that transform shared state, connect them into directed graphs, add routers for conditional routing, integrate tools (calculator and web search), and combine everything into a simple research agent.
Table of contents
* Environment setup
* Task overview
* Task 1 — Imports & minimal state
* Task 2 — Simple nodes
* Task 3 — Wiring nodes with edges
* Task 4 — Multi-step flow (outline → draft → review)
* Task 5 — Conditional routing (routers)
* Task 6 — Tool integration (calculator)
* Task 7 — Research agent: combining tools (DDGS + calculator + LLM)
* Architecture diagrams
* Integrating external systems with self-describing interfaces
* Further exploration
* Links & references
Environment setup
Prepare a virtual environment and install the runtime dependencies used in these examples: LangGraph, LangChain, an OpenAI wrapper, and the DuckDuckGo search client (`ddgs`). After installation, optionally run a verification script if you have one.
```bash theme={null}
cd /root
source /root/venv/bin/activate
pip install langgraph langchain langchain-openai ddgs
# Optionally run a verification script if provided:
# python3 /root/code/verify_setup.py
```
Activate the virtual environment in every new shell where you run these examples. Use a requirements file or pinned versions in production to ensure reproducible installs.
Task overview
| Task | Goal |
| ------ | ------------------------------------------------------------------------- |
| Task 1 | Verify imports and define a minimal `State` TypedDict |
| Task 2 | Implement simple node functions that return partial state updates |
| Task 3 | Connect nodes in a `StateGraph` and execute a linear workflow |
| Task 4 | Build a multi-step content pipeline (outline → draft → review) |
| Task 5 | Add routers for conditional branching |
| Task 6 | Integrate a tool (calculator) safely |
| Task 7 | Combine a calculator, web search (ddgs), and an LLM into a research agent |
Task 1 — Understanding imports and basic state definition
Start by importing the core classes from LangGraph and creating a minimal `State` type used by the graph runtime.
```python theme={null}
from langgraph.graph import StateGraph, END
from typing import TypedDict, List
print("🍕 Task 1: Understanding Imports\n")
class State(TypedDict):
messages: List[str]
# Test that imports work by constructing a StateGraph
print("Testing imports...")
try:
test_graph = StateGraph(State)
print("✅ StateGraph imported and constructed successfully!")
except Exception as e:
print("❌ Error constructing StateGraph:", e)
```
What to remember
* `StateGraph` represents the workflow and enforces the shape of the shared state.
* `END` is used to mark termination nodes in more advanced flows.
* `TypedDict` helps document and type-check the keys passed across nodes.
Task 2 — Creating simple nodes
Nodes are plain Python functions that accept the global `state` and return only the partial state updates they produce. Below are two example nodes: `greet_node` and `enhance_node`. We also show how to merge returned partial state with the running state (the graph runtime normally handles this merge).
```python theme={null}
import time
from typing import TypedDict
class State(TypedDict):
name: str
greeting: str
def greet_node(state: State):
"""Create a greeting from the name."""
print("⏳ Processing in greet_node...")
time.sleep(1) # Simulate processing time
greeting = f"Hello, {state['name']}!"
print("Node returned:", {"greeting": greeting})
return {"greeting": greeting}
def enhance_node(state: State):
"""Enhance the greeting with a follow-up question."""
print("⏳ Processing in enhance_node...")
time.sleep(1)
enhanced = state["greeting"] + " How are you?"
print("Node returned:", {"greeting": enhanced})
return {"greeting": enhanced}
# Test nodes directly (no graph)
initial_state: State = {"name": "Alice", "greeting": ""}
g = greet_node(initial_state)
state_after_greet = {**initial_state, **g}
print("State after greet:", state_after_greet)
h = enhance_node(state_after_greet)
final_state = {**state_after_greet, **h}
print("Final state:", final_state)
```
Key points
* Nodes return only the fields they update (partial state).
* The graph runtime merges these partial updates into the running state.
Task 3 — Wiring nodes with edges
Use `StateGraph` to compose nodes into directed workflows. The graph runtime invokes nodes following the topology you define via edges and entry points.
```python theme={null}
from langgraph.graph import StateGraph, END
from typing import TypedDict
import time
class State(TypedDict):
name: str
greeting: str
def greet_node(state: State):
print("⏳ Processing in greet_node...")
time.sleep(1)
return {"greeting": f"Hello, {state['name']}!"}
def enhance_node(state: State):
print("⏳ Processing in enhance_node...")
time.sleep(1)
return {"greeting": state["greeting"] + " How are you?"}
# Build a graph and add nodes/edges
graph = StateGraph(State)
graph.add_node("greet", greet_node)
graph.add_node("enhance", enhance_node)
graph.add_edge("greet", "enhance")
graph.set_entry_point("greet")
# Invoke the graph with an initial state
initial_state: State = {"name": "Alice", "greeting": ""}
result = graph.invoke(initial_state)
print("Graph result:", result)
```
This constructs a simple linear workflow: `greet` → `enhance`. The graph runtime handles ordering and state merging.
Task 4 — Multi-step flow (draft & review)
Workflows often have several transformation steps. The following example shows an `outline` → `draft` → `review` pipeline, where each node adds or refines pieces of the document.
```python theme={null}
from langgraph.graph import StateGraph
from typing import TypedDict
import time
class State(TypedDict):
topic: str
outline: str
draft: str
final: str
def outline_node(state: State):
print("📝 Creating outline...")
time.sleep(1)
return {"outline": f"Outline for '{state['topic']}':\n1. Introduction\n2. Main points\n3. Conclusion"}
def draft_node(state: State):
print("✍️ Writing draft from outline...")
time.sleep(1)
return {"draft": f"Draft: Expanding on the outline for '{state['topic']}' based on:\n{state['outline']}"}
def review_node(state: State):
print("🔍 Reviewing draft...")
time.sleep(1)
return {"final": f"Final: Reviewed and polished content about '{state['topic']}'. Ready to publish!"}
graph = StateGraph(State)
graph.add_node("outline", outline_node)
graph.add_node("draft", draft_node)
graph.add_node("review", review_node)
graph.add_edge("outline", "draft")
graph.add_edge("draft", "review")
graph.set_entry_point("outline")
initial_state: State = {"topic": "LangGraph Basics", "outline": "", "draft": "", "final": ""}
result = graph.invoke(initial_state)
print("=" * 50)
print("WORKFLOW RESULTS:")
print("Topic:", result["topic"])
print("Outline:", result["outline"])
print("Draft:", result["draft"][:80] + "..." if len(result["draft"]) > 80 else result["draft"])
print("Final:", result["final"])
print("=" * 50)
```
Benefits of multi-step flows
* Encourages single-responsibility nodes.
* Easier debugging and targeted retries.
* State captures intermediate artifacts useful for observability.
Task 5 — Conditional routing (routers)
Routers enable state-driven branching: inspect the state and return the next node name. This pattern supports dynamic workflows such as choosing between a quick answer or a detailed response.
```python theme={null}
from langgraph.graph import StateGraph
from typing import TypedDict
import time
class State(TypedDict):
query: str
query_length: str # "short" or "detailed"
response: str
def classify_length(state: State):
print("🔍 Classifying query length...")
time.sleep(0.5)
qlen = "short" if len(state["query"]) < 30 else "detailed"
return {"query_length": qlen}
def quick_answer_node(state: State):
print("⚡ Providing a quick answer...")
return {"response": f"Quick answer to: {state['query']}"}
def detailed_answer_node(state: State):
print("🧩 Providing a detailed answer...")
return {"response": f"Detailed response to: {state['query']}"}
def router(state: State):
if state["query_length"] == "short":
return "quick_answer"
return "detailed_answer"
graph = StateGraph(State)
graph.add_node("classify_length", classify_length)
graph.add_node("quick_answer", quick_answer_node)
graph.add_node("detailed_answer", detailed_answer_node)
graph.add_router("classify_length", router) # router decides next node after classification
graph.set_entry_point("classify_length")
res = graph.invoke({"query": "What is Python?", "query_length": "", "response": ""})
print("Query:", res["query"])
print("Route taken:", res["query_length"])
print("Response:", res["response"])
```
Routers let you build flexible, branchable workflows driven by runtime state.
Task 6 — Tool integration (calculator)
Tools are nodes that encapsulate specialized capabilities. The example below demonstrates a simple calculator tool and a detector that decides whether to use it.
```python theme={null}
from langgraph.graph import StateGraph
from typing import TypedDict
import math
class State(TypedDict):
query: str
is_math: bool
result: str
def math_detector(state: State):
# Very simple heuristic; real systems would use an LLM classifier
is_math = any(ch.isdigit() for ch in state["query"]) and any(op in state["query"] for op in ["+", "-", "*", "/"])
return {"is_math": is_math}
def calculator_tool(state: State):
print("🧮 Processing with calculator...")
try:
# WARNING: Using eval is dangerous; in production use a safe math parser
answer = str(eval(state["query"], {"__builtins__": {}}, {}))
except Exception as e:
answer = f"Error calculating expression: {e}"
return {"result": answer}
def default_answer(state: State):
return {"result": "This is not a math question. Please ask a calculation!"}
def router(state: State):
return "calculator" if state["is_math"] else "default"
graph = StateGraph(State)
graph.add_node("math_detector", math_detector)
graph.add_node("calculator", calculator_tool)
graph.add_node("default", default_answer)
graph.add_router("math_detector", router)
graph.set_entry_point("math_detector")
# Example: non-math
res = graph.invoke({"query": "What is the weather today?", "is_math": False, "result": ""})
print("Query:", res["query"])
print("Result:", res["result"])
# Example: math
res2 = graph.invoke({"query": "2 + 2 * 3", "is_math": False, "result": ""})
print("Query:", res2["query"])
print("Result:", res2["result"])
```
Never use `eval` on untrusted input in production. Replace it with a safe mathematical expression evaluator or sandboxed execution environment.
Task 7 — Research Agent: combining tools (DDGS + calculator + LLM)
Combine classification, routing, a calculator tool, and a DuckDuckGo search client to build a small research agent. This example shows how to integrate external tools and orchestrate them with LangGraph.
```python theme={null}
import os
import time
from typing import TypedDict
from ddgs import DDGS
from langchain.chat_models import ChatOpenAI # or other LLM wrapper
from langgraph.graph import StateGraph
class State(TypedDict):
query: str
query_type: str # "math" or "search"
result: str
# Initialize LLM (example)
llm = ChatOpenAI(
model_name=os.getenv("OPENAI_MODEL", "gpt-4o-mini"),
temperature=0.7,
openai_api_key=os.getenv("OPENAI_API_KEY"),
openai_api_base=os.getenv("OPENAI_API_BASE")
)
# Initialize DuckDuckGo search client
ddgs = DDGS()
def classify_query(state: State):
"""Classify query as math or search using simple heuristics or LLM."""
print("🔍 Analyzing query type...")
time.sleep(0.5)
# Simple heuristic for demo; replace with LLM classification as needed
q = state["query"].lower()
is_math = any(ch.isdigit() for ch in q) and any(op in q for op in ["+", "-", "*", "/"])
return {"query_type": "math" if is_math else "search"}
def router(state: State):
if state["query_type"] == "math":
return "calculator_tool"
return "search_tool"
def calculator_tool(state: State):
print("🧮 Calculator tool invoked for:", state["query"])
try:
answer = str(eval(state["query"], {"__builtins__": {}}, {}))
except Exception as e:
answer = f"Error calculating expression: {e}"
return {"result": f"Answer: {answer}"}
def search_tool(state: State):
print("🔎 Searching the web for:", state["query"])
# Perform a simple search and collect top results
results = []
try:
with ddgs as client:
for r in client.search(state["query"], max_results=3):
results.append(f"- {r.get('title', '')}: {r.get('body', '')}")
except Exception as e:
results = [f"Search error: {e}"]
content = "Search results:\n" + "\n".join(results)
return {"result": content}
# Build graph
graph = StateGraph(State)
graph.add_node("classify", classify_query)
graph.add_node("calculator_tool", calculator_tool)
graph.add_node("search_tool", search_tool)
graph.add_router("classify", router)
graph.set_entry_point("classify")
# Test: math query
math_test = {"query": "12 / (2 + 4)", "query_type": "", "result": ""}
print("\nTEST 1: Math query")
res_math = graph.invoke(math_test)
print("Result:", res_math["result"])
# Test: search query
search_test = {"query": "What is LangGraph used for?", "query_type": "", "result": ""}
print("\nTEST 2: Search query")
res_search = graph.invoke(search_test)
print("Result:", res_search["result"][:300], "...")
```
This research agent demonstrates:
* Classification of queries (heuristic or LLM-based)
* Conditional routing to specialized tools
* Integration with external search (DuckDuckGo via `ddgs`)
* Orchestration of tools and LLMs in a single `StateGraph`
Integrating external systems with self-describing interfaces
TechCorp's internal AI document assistant works well for internal content, but real-world deployments need access to external systems such as customer databases, ticketing systems, inventory, and third-party APIs. Building a custom adapter for each system quickly becomes costly and brittle.
A model-facing, self-describing interface reduces this friction. Instead of exposing raw endpoints tied to low-level implementation details, these interfaces expose machine-readable capability descriptions that agents can query and invoke. Advantages include:
* Easier discovery of available actions and required inputs
* Reduced brittle, hand-coded adapter logic
* Safer orchestration across heterogeneous systems
In practice, a self-describing interface might provide an OpenAPI-like schema, examples of usage, and type-safe I/O contracts the agent can read at runtime to plan its interactions.
Best practices when integrating external tools
* Use machine-readable schemas (OpenAPI, JSON Schema) to let agents discover capabilities.
* Implement authentication, role-based access control, and audit logging.
* Provide clear error semantics so agents can retry or escalate correctly.
* Validate and sanitize inputs; never run untrusted code directly.
Further exploration
* Replace simple heuristics with LLM-based classifiers to improve routing decisions.
* Use safe math parsers (e.g., `asteval`, `numexpr`, or a dedicated math library) rather than `eval`.
* Add caching or vector search (RAG) to improve performance and relevance for search-oriented tools.
* Implement observability (tracing, logs, per-node metrics) for reliability and debugging.
* Experiment with multi-agent orchestration and cross-graph communication patterns.
Links and references
* LangGraph (project) — [LangGraph docs](https://github.com/langgraph) (replace with the official docs link as available)
* LangChain — [https://langchain.dev/](https://langchain.dev/)
* DuckDuckGo Search (ddgs) — [https://pypi.org/project/ddgs/](https://pypi.org/project/ddgs/)
* OpenAI API and Chat Models — [https://platform.openai.com/docs/](https://platform.openai.com/docs/)
Happy building!
# Practice Labs RAG Implementation
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-2/Practice-Labs-RAG-Implementation/page
Guide to building a Retrieval-Augmented Generation pipeline using ChromaDB, sentence-transformers, smart chunking, prompt engineering, and LLM integration for grounded answers with source attributions.
This lesson extends a semantic search system into a Retrieval-Augmented Generation (RAG) pipeline. Instead of returning only matching documents (for example, returning `remote-work-policy.pdf` for the query "work from home"), the RAG pipeline retrieves relevant context and uses a large language model (LLM) to generate concise, grounded answers such as: "Yes — employees may work up to three days per week from home."
Key concepts covered:
* Vector store initialization and persistence (ChromaDB)
* Semantic embeddings with sentence-transformers
* Smart document chunking for context preservation
* LLM integration and prompt engineering for RAG
* A complete pipeline that returns answers with source attributions
Project files:
| File | Purpose |
| -------------------------------- | ----------------------------------------------- |
| README.md | Project overview and instructions |
| task\_1\_setup\_vectorstore.py | Initialize ChromaDB and load embedding model |
| task\_2\_document\_processing.py | Document parsing and smart chunking |
| task\_3\_llm\_integration.py | LLM client initialization and test generation |
| task\_4\_prompt\_engineering.py | Build RAG-safe prompts that avoid hallucination |
| task\_5\_complete\_rag.py | End-to-end RAG pipeline orchestration |
| verify\_environment.py | Environment and dependency verification |
***
## Environment setup and verification
Install required libraries. Common libraries used in this lab:
* ChromaDB (vector database): [https://www.trychroma.com/](https://www.trychroma.com/)
* Sentence Transformers (embeddings): [https://www.sbert.net/](https://www.sbert.net/)
* LangChain (RAG orchestration): [https://python.langchain.com/](https://python.langchain.com/)
* OpenAI-compatible model endpoints (for example, GPT-4.1 Mini)
After installing, run the verification script to confirm dependencies and environment variables are available:
```bash theme={null}
# Run the verification script
python3 /root/code/verify_environment.py
```
Example verification output:
```bash theme={null}
🔧 RAG Lab Environment Verification
===================================
📦 Checking Python Environment:
✅ Virtual environment is active
📦 Checking Required Packages:
✅ ChromaDB (vector database) available
✅ Sentence Transformers (embeddings) available
✅ LangChain (RAG framework) available
```
Once dependencies are confirmed, proceed to initialize the vector store and embedding model.
***
## Task 1 — Setup the vector store (ChromaDB)
Create a persistent ChromaDB client and a collection to store document embeddings. Load the sentence-transformers model `all-MiniLM-L6-v2` (384-d vectors) to embed document chunks and queries.
Example setup code (task\_1\_setup\_vectorstore.py):
```python theme={null}
# task_1_setup_vectorstore.py
from sentence_transformers import SentenceTransformer
import chromadb
print("=" * 50)
# 1: Initialize ChromaDB client for persistent storage
client = chromadb.PersistentClient(path="./chroma_db")
print("✅ ChromaDB client initialized")
# 2: Create or get collection named "techcorp_rag"
collection = client.get_or_create_collection(name="techcorp_rag")
print(f"✅ Collection '{collection.name}' ready")
# 3: Initialize embedding model for 384-dimension vectors
model = SentenceTransformer("all-MiniLM-L6-v2")
print("✅ Embedding model loaded")
# test the setup
test_text = "Testing RAG setup"
test_embedding = model.encode(test_text)
print(f"✅ Test embedding created: {len(test_embedding)} dimensions")
```
Expected run summary:
```bash theme={null}
vocab.txt: 232kB [00:00, 9.61MB/s]
tokenizer.json: 466kB [00:00, 26.7MB/s]
special_tokens_map.json: 100%
config.json: 100%
(✅) Embedding model loaded
(✅) Test embedding created: 384 dimensions
=> SUCCESS! Your vector store is ready for RAG!
- ChromaDB initialized
- Collection: techcorp_rag
- Embedding model: all-MiniLM-L6-v2
- Vector dimensions: 384
```
This collection is your persistent RAG memory where company documents are stored as vectors for semantic retrieval.
***
## Task 2 — Document processing and smart chunking
Chunking strategy is critical for RAG quality. Prefer paragraph-based chunking with small overlaps so chunks preserve complete thoughts and transitions. This helps the LLM use coherent context without requiring large token budgets.
Example implementation (task\_2\_document\_processing.py):
```python theme={null}
# task_2_document_processing.py
from pathlib import Path
from typing import List
import os
def smart_chunk_document(text: str, max_paragraphs_per_chunk: int = 3, overlap_paragraphs: int = 1) -> List[str]:
"""
Chunk text by paragraphs, grouping up to max_paragraphs_per_chunk paragraphs per chunk.
Apply a small overlap so adjacent chunks share overlap_paragraphs to preserve continuity.
"""
paragraphs = [p.strip() for p in text.split("\n\n") if p.strip()]
if not paragraphs:
return []
chunks = []
i = 0
while i < len(paragraphs):
prev_i = i
end = min(i + max_paragraphs_per_chunk, len(paragraphs))
chunk = "\n\n".join(paragraphs[i:end])
chunks.append(chunk)
# If we've reached the end, break
if end >= len(paragraphs):
break
# advance with overlap: start next chunk overlap_paragraphs paragraphs before end,
# but ensure progress to avoid infinite loops
i = end - overlap_paragraphs
if i <= prev_i:
i = end
return chunks
# Process documents
doc_dir = Path("/root/techcorp-docs")
total_chunks = 0
docs_processed = 0
for category_dir in doc_dir.iterdir():
if category_dir.is_dir():
print(f"\n📁 Processing {category_dir.name}:")
for doc_file in category_dir.glob("*.md"):
metadata = {
"source": doc_file.name,
"section": category_dir.name
}
with open(doc_file, "r", encoding="utf-8") as f:
content = f.read()
chunks = smart_chunk_document(content, max_paragraphs_per_chunk=3, overlap_paragraphs=1)
# Example: here you would encode chunks and add them to ChromaDB with metadata
total_chunks += len(chunks)
docs_processed += 1
print(f"\nProcessed {docs_processed} documents into {total_chunks} chunks.")
```
Notes:
* Paragraph-based chunking preserves semantics better than fixed-character slices.
* Make chunk size and overlap parameters configurable for tuning to prompt token limits.
***
## Task 3 — LLM integration
Connect a deterministic, production-ready LLM client (for example, GPT-4.1 Mini via an OpenAI-compatible client). Use conservative generation settings (low temperature, token limits) to reduce hallucination and produce concise answers.
Example code (task\_3\_llm\_integration.py):
```python theme={null}
# task_3_llm_integration.py
from langchain.chat_models import ChatOpenAI
# Initialize client (API key and base should be configured in your environment)
client = ChatOpenAI(model="openai/gpt-4.1-mini")
print("✅ OpenAI client initialized")
def test_generation(client):
"""Test basic LLM generation"""
temperature = 0.3 # focused, lower chance of hallucination
max_tokens = 500 # concise answers
client.temperature = temperature
client.max_tokens = max_tokens
print(f"\n🔬 Testing openai/gpt-4.1-mini with temperature={temperature}")
messages = [
{"role": "system", "content": "You are a helpful AI assistant."},
{"role": "user", "content": "What is RAG in AI? Answer in one sentence."},
]
# Use client's chat completion method appropriate to your SDK (example below)
response = client(messages)
print("\n● Test Response:", response.content)
```
Example test output:
```bash theme={null}
🔬 Testing openai/gpt-4.1-mini with temperature=0.3
● Test Response: RAG (Retrieval-Augmented Generation) in AI is a technique that combines retrieval of relevant documents from a large dataset with generative models to produce more accurate and contextually informed responses.
```
With the LLM client verified, you can assemble a RAG prompt template and wire retrieval and generation together.
***
## Task 4 — Prompt engineering for RAG
Craft a prompt template that:
* Injects retrieved context chunks into the prompt,
* Explicitly instructs the model to answer only from the provided context,
* Requires a fixed fallback phrase when the context does not contain the answer to avoid hallucination.
Example prompt builder (task\_4\_prompt\_engineering.py):
```python theme={null}
# task_4_prompt_engineering.py
def create_rag_prompt(context_chunks, user_question):
"""
Build a system and user prompt that forces the model to use only the provided context.
If the information is not in the context, the model must say:
"I don't have that information in the provided documents."
"""
system_prompt = (
"You are a helpful AI assistant. Answer the user's question using ONLY the information "
"present in the provided context chunks. If the answer is not contained in the context, "
"reply exactly: \"I don't have that information in the provided documents.\" "
"Be concise and accurate."
)
# Build context section from retrieved chunks
context_text = "Context from TechCorp documents:\n\n"
for i, chunk in enumerate(context_chunks, 1):
context_text += f"[Document {i}]\n{chunk}\n\n"
# Create the user prompt with context and question
user_prompt = f"""{context_text}
Question: {user_question}
Answer:"""
return system_prompt, user_prompt
# Example test
context_chunks = ["TechCorp allows up to 3 days/week remote work.", "During emergencies, 100% remote may be authorized."]
system_prompt, user_prompt = create_rag_prompt(context_chunks, "How many days per week can employees work from home?")
print(system_prompt)
print(user_prompt)
```
Design prompts that explicitly constrain the model to the retrieved context and provide a clear fallback phrase for missing information to prevent hallucinations.
Example generated answer (illustrative):
```text theme={null}
You can work from home up to 3 days per week.
Sources: remote-work-policy.md
```
***
## Task 5 — Complete RAG pipeline
Assemble the end-to-end pipeline:
1. Embed the user's query using the same embedding model that encoded document chunks.
2. Query ChromaDB for top-k most relevant chunks (semantic search).
3. Build a context-aware prompt from those chunks.
4. Send the system + user prompt to the LLM to generate an answer.
5. Return the answer along with source attributions (document metadata).
Example pipeline (task\_5\_complete\_rag.py):
```python theme={null}
# task_5_complete_rag.py
import os
def test_rag_pipeline(collection, embedding_model, llm_client, user_question, top_k=3):
# 1. Embed the question
q_emb = embedding_model.encode(user_question)
# 2. Query the collection (ChromaDB query interface may vary)
results = collection.query(
query_embeddings=[q_emb],
n_results=top_k,
include=["metadatas", "documents", "distances"]
)
# Extract chunks and sources
retrieved_chunks = []
sources = set()
docs = results.get("documents", [[]])[0]
metadatas = results.get("metadatas", [[]])[0]
for i, doc_text in enumerate(docs):
if not doc_text:
continue
retrieved_chunks.append(doc_text)
meta = metadatas[i] if i < len(metadatas) else {}
if meta.get("source"):
sources.add(meta["source"])
# 3. Build prompts
system_prompt, user_prompt = create_rag_prompt(retrieved_chunks, user_question)
# 4. Call LLM (example usage; adapt to your SDK)
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
]
response = llm_client(messages)
# 5. Return result with sources
answer_text = response.content.strip()
return answer_text, list(sources)
# Example orchestration
if __name__ == "__main__":
try:
# Assume collection, model, and client are initialized as in earlier tasks
print(f"\n⏳ Database has {collection.count()} chunks ready")
answer, sources = test_rag_pipeline(collection, model, client, "Can I work from home three days a week?")
print("\nGENERATE: Creating answer...\n")
print("ANSWER:")
print(answer)
print("\nSources:", ", ".join(sources))
print("\n" + "=" * 50)
print(" 🧪 RAG Pipeline Complete!")
print(" - Retrieval: Semantic search working")
print(" - Augmentation: Context injection ready")
print(" - Generation: LLM producing answers")
print(" - Citations: Sources included")
print("=" * 50)
# Create marker file
os.makedirs("/root/markers", exist_ok=True)
with open("/root/markers/task5_rag_complete.txt", "w") as f:
f.write("TASK5_COMPLETE:RAG_PIPELINE_READY")
except Exception as e:
print(f"\n❌ Error: {e}")
print("\n✅ You've built a complete RAG system — from search to answers!")
```
Example run and result (illustrative):
```bash theme={null}
⏳ Database has 124 chunks ready
GENERATE: Creating answer...
ANSWER:
TechCorp's remote work policy embraces flexible work arrangements to promote work-life balance and productivity. It outlines a hybrid work model and remote work guidelines. During emergency situations such as severe weather or health emergencies, 100% remote work may be authorized; essential personnel are notified separately, and the business continuity plan is activated.
Sources: remote-work-policy.md, remote-work.md
============================================================
🎉 RAG Pipeline Complete!
- Retrieval: Semantic search working
- Augmentation: Context injection ready
- Generation: LLM producing answers
- Citations: Sources included
============================================================
```
This pattern ensures queries are answered using retrieved context and that sources are included for traceability and auditability.
***
## Practical considerations and next steps
* Tune chunking size and overlap to balance contextual completeness against token limits for your target LLM.
* Experiment with embedding models (quality vs. cost) and with LLM temperature/length settings.
* Add filters for document recency, confidentiality tags, or department-level access control.
* Implement caching, rate limiting, and logging for production usage.
* Consider connecting to HR systems or identity-aware access control when answers depend on user-specific entitlements.
Handle confidential or restricted documents with care. Ensure access controls and document classification are enforced before including sensitive content in embeddings or returning it in generated answers.
Suggested links and references:
* [ChromaDB Documentation](https://www.trychroma.com/)
* [Sentence Transformers Models](https://huggingface.co/sentence-transformers)
* [LangChain Documentation](https://python.langchain.com/)
* [OpenAI Platform](https://platform.openai.com/)
The diagram above illustrates the simple chat app architecture: documents are embedded into a vector DB, relevant chunks are retrieved for a user question, and an LLM produces a grounded answer that includes source attributions.
You're now set up with a working RAG architecture — retrieval, augmentation, and generation — ready to iterate and adapt for your production use case.
# RAG
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-2/RAG/page
Explains Retrieval-Augmented Generation combining vector retrieval and context injection to provide accurate, up-to-date LLM answers from private documents with engineering guidance.
Instead of scanning 500 GB of documents into a model's context window, Retrieval-Augmented Generation (RAG) lets an AI assistant find and use only the most relevant content at query time. RAG combines semantic search over a vector database with prompt-time context injection so an LLM can generate accurate, up-to-date answers without retraining.
Example user question: "What's our remote work policy for international employees?"\
With RAG, the assistant locates the exact policy passages and uses them to produce a targeted, current response.
RAG can be understood as three sequential steps: Retrieval, Augmentation, and Generation.
## 1) Retrieval
* Convert documents and the incoming user question into vector embeddings.
* Compare the query embedding against stored document embeddings in a vector database using semantic similarity.
* Return the top-matched documents or document chunks (not simple keyword matches — the search finds semantically related passages).
Why embeddings and vector search? Because they let you find content that matches the meaning of the question (e.g., "remote work policy for international employees") even when the wording differs across documents.
## 2) Augmentation
Augmentation injects the retrieved text snippets into the model’s prompt at runtime. Typical augmentation steps:
* Select the top-k passages returned by the vector search.
* Optionally filter or re-rank passages by metadata, recency, or source trust.
* Insert these passages into a prompt template so the LLM can reference them while generating an answer.
RAG usually avoids costly model fine-tuning: you provide retrieved context at runtime so a base LLM can generate accurate answers using up-to-date, private data without being retrained.
## 3) Generation
* The LLM receives a prompt that includes the user question plus the retrieved context.
* The model synthesizes information from those passages and its own knowledge to produce a coherent, accurate answer tailored to the query (for example, applying policy details to "international employees").
This matters because legal documents often contain long, structured paragraphs
that need to be preserved and intact, while conversational transcripts can be split at the sentence or paragraph level.
## Why RAG matters
* Extends an LLM’s effective knowledge beyond its training cutoff by supplying current documents at query time.
* Enables private, domain-specific answers without embedding proprietary data into model weights.
* Preserves context fidelity by surfacing the exact passages used to answer a question, improving traceability and trust.
## Calibrating and designing a RAG system
Getting reliable outputs requires careful design and iterative tuning. Key factors include chunking, retrieval size, scoring, and prompt templates.
| Design factor | Effect on results | Practical recommendation |
| ------------------------------------ | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| Chunk size & overlap | Too-small chunks lose context; too-large chunks reduce retrieval granularity | Use larger, structure-preserving chunks for legal/technical docs; use sentence/paragraph chunks for transcripts |
| Number of retrieved passages (k) | Small k may miss relevant info; large k can introduce noise | Start with k=3–10 and tune by task / dataset |
| Similarity scoring & normalization | Affects ranking fairness across sources and lengths | Normalize by passage length and use re-ranking with metadata when needed |
| Prompt templates & context injection | Determines how well the model uses the retrieved passages | Provide clear instructions and cite sources/footnotes in the prompt |
Common engineering considerations:
* Preserve important structure (headings, numbered lists, dates) when chunking.
* Store metadata (source, timestamp, author) with embeddings for filtering and auditing.
* Use recency or source trust to weight retrievals when answers must favor the latest policy or authoritative documents.
* Evaluate with end-to-end metrics: precision/recall of retrieved passages, hallucination rate, and human feedback loops.
## Implementation resources
* Vector databases and similarity search: Pinecone, Weaviate, Milvus
* Embeddings and semantic search guides: OpenAI Embeddings, semantic search overview
* Prompt design and safety: best practices for context injection and hallucination mitigation
Links and references:
* [Pinecone Vector Database](https://www.pinecone.io/)
* [Weaviate](https://weaviate.io/)
* [Milvus](https://milvus.io/)
* [Semantic Search (overview)](https://en.wikipedia.org/wiki/Semantic_search)
* [OpenAI Embeddings](https://platform.openai.com/docs/guides/embeddings)
RAG is a practical pattern to deliver timely, accurate, and auditable answers from private collections. Building an effective pipeline is an engineering process—choose chunking strategies and retrieval parameters that match your document types, and iterate on prompt and retrieval design to reduce noise and improve reliability.
# Vector Databases Deep Dive
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/AI-Agents-Part-2/Vector-Databases-Deep-Dive/page
Describes how embeddings and vector databases power semantic search and RAG, including chunking, similarity metrics, indexing options, and deployment trade offs for production
Large language models (LLMs) rely on a context window to process input and generate useful responses. When an organization like TechCorp needs to search 500 GB of internal documents, traditional keyword search struggles with semantic variation (e.g., “vacation” vs “time off”). Embeddings and vector databases enable semantic search at scale and are a common foundation for retrieval-augmented generation (RAG) applications built with frameworks such as LangChain.
Problem scenario
* Suppose the 500 GB dataset contains an employee handbook covering policies like time off, dress code, and equipment use.
* Users may phrase the same intent using different words: “vacation policy”, “time off guidelines”, or “Can I request time off on a holiday?” Keyword-based search often misses relevant content unless the exact words are present.
Traditional SQL / keyword approach
* SQL and text-index approaches use exact or pattern matching (LIKE, full-text search). Users must guess correct words or rely on manual synonym expansion.
```sql theme={null}
-- Traditional SQL approach: keyword search
SELECT * FROM documents
WHERE content LIKE '%Vacation%' OR content LIKE '%vacation policy%';
-- Example user query:
-- "Can I request time off on a holiday?"
```
* Drawbacks: brittle to phrasing, requires query engineering, and often produces noisy or incomplete results.
Why embeddings + vector databases?
* Embeddings convert text into fixed-length numeric vectors that capture semantic meaning. Related texts (e.g., “vacation” and “holiday”) map to nearby vectors in the embedding space.
* When a user asks a natural language question, the system compares the embedding of the query with document embeddings and returns semantically similar content even if the wording differs.
* This approach is ideal for RAG systems and LLM-driven assistants because it surfaces relevant context without retraining the LLM.
Popular vector databases and when to use them
| Vector Database | Best Use Case | Notes |
| --------------- | ------------------------------------------------- | ----------------------------------------------------- |
| Pinecone | Production-grade semantic search at scale | Managed service, easy integration, strong performance |
| ChromaDB | Local prototyping and small-to-medium deployments | Open-source, developer-friendly embedding store |
(Also commonly used: FAISS for offline/embedded ANN indexing, Milvus for large-scale open-source vector search.)
Embeddings: turning text into meaning
* Embedding models map text chunks (sentences, paragraphs) to numeric vectors. Similar meanings yield nearby vectors.
* Example workflow:
1. Split documents into chunks (paragraphs or sections).
2. Call an embedding model to convert each chunk into a vector.
3. Store vectors in a vector DB with metadata (source, offsets, timestamps).
4. For a user query, embed the query and retrieve the nearest vectors (top-K or above a threshold).
* Benefit: the LLM receives relevant passages for context regardless of exact phrasing.
Dimensionality trade-offs
| Dimension size | Pros | Cons |
| -------------- | ----------------------------------------------------- | -------------------------------------------------- |
| \~256 | Lower storage & compute | May miss fine-grained semantic distinctions |
| \~768–1536 | Good semantic expressiveness (common for many models) | Higher storage & retrieval cost |
| >1536 | Captures more nuance | Increased cost; diminishing returns beyond a point |
* Choose dimensionality based on the embedding model you select and the latency/storage budget.
Retrieval: scoring and chunking
Two core decisions determine retrieval quality: similarity scoring and how you chunk documents.
Scoring / similarity metrics
* Common similarity measures:
* Cosine similarity: robust when vectors are length-normalized.
* Dot product: often used for models that produce normalized vectors or when scaling factors matter.
* Index types:
* Exact: brute-force nearest neighbors (slow for large corpora).
* ANN (approximate): e.g., HNSW — trades minimal accuracy for large speed and memory gains.
* Tuning:
* Choose top-K results and/or a similarity threshold to filter noisy matches.
* Too-low thresholds can return loosely related content (false positives); too-high may omit relevant passages.
Chunking and overlap
* Rather than embedding whole documents, split into chunks (paragraphs, sliding windows) and embed each chunk.
* Overlap windows (e.g., 200-token chunks with 50-token overlap) preserve context across boundaries.
* Trade-offs:
* Smaller chunks → more precise matches, but more vectors to store and search.
* Larger chunks → fewer vectors but higher risk of mixing topics and lowering retrieval precision.
Comparison: SQL vs Vector-based retrieval
| Characteristic | SQL / Keyword Search | Vector / Embedding Search |
| ------------------------ | --------------------------------- | --------------------------------------------- |
| Query type | Keyword/pattern matching | Natural language / semantic |
| Robustness to paraphrase | Low | High |
| Setup complexity | Low | Medium–High (embeddings, chunking, indexes) |
| Best for | Exact matches, structured queries | Unstructured documents, LLM context retrieval |
Operational considerations and trade-offs
* Design choices: embedding model, dimensionality, chunk size, overlap, similarity metric, ANN configuration, scoring thresholds.
* Costs: storage for vectors, runtime cost of embedding generation, and compute for ANN queries.
* Monitoring: track retrieval precision, false positives, and downstream LLM output quality to iterate on knobs.
* Integration: vector DBs pair well with LangChain-style retrieval chains and RAG pipelines for chatbots and assistants.
Resources and next steps
* Prototype: use a small subset of documents with an open-source embedding model and Chroma/FAISS to validate chunk size and overlap choices.
* Production: evaluate managed options (Pinecone, managed Milvus) for indexing, scaling, and operational support.
* RAG integration: feed retrieved chunks into your LLM prompt or LangChain retrieval chain and measure answer quality.
When designing a vector-backed retrieval system, treat embedding creation, chunking strategy, similarity metric, and scoring thresholds as tunable knobs. Proper configuration upfront reduces noise in retrieval and improves downstream LLM responses.
Links and references
* [LangChain course](https://learn.kodekloud.com/user/courses/langchain)
* [Fundamentals of RAG](https://learn.kodekloud.com/user/courses/fundamentals-of-rag)
* [Pinecone](https://www.pinecone.io)
* [ChromaDB](https://www.trychroma.com)
* [Kubernetes Documentation](https://kubernetes.io/docs/) (general infra reference)
# Course Introduction
Source: https://notes.kodekloud.com/docs/AI-Agents-Fundamentals/Introduction/Course-Introduction/page
Hands-on course teaching semantic search, RAG, vector databases, and graph-based stateful AI agents with labs, code examples, and production deployment practices.
Welcome to the AI Agents Fundamentals course. AI-driven applications are transforming industries by enabling systems to reason, remember, and act — automating workflows and augmenting decision-making.
This lesson provides a hands-on path from your first API call to building production-quality, stateful AI agents. You’ll move from environment verification to implementing semantic search, Retrieval-Augmented Generation (RAG), and graph-based workflows that maintain memory and reasoning. Labs include runnable code examples so you can quickly move from theory to practical implementation.
What you’ll learn
* Make your first AI API call and understand modern model interactions.
* Build and deploy AI features using agent frameworks and prompt engineering best practices.
* Implement vector databases and a semantic search engine for technical documentation to retrieve by meaning rather than keywords.
* Combine retrieval and generation using Retrieval-Augmented Generation (RAG) for more accurate, context-aware outputs.
* Design stateful, graph-based workflows and agents that remember, reason, and react over time.
* Extend workflows with external tools, observability, and production-ready safety patterns.
Course modules summary
| Module | Focus | Outcome |
| ---------------------------------- | -------------------------------------------------- | ------------------------------------------------- |
| Environment & Setup | Verify virtualenv and Python packages | Run a verification script to confirm dependencies |
| Vector Search & Semantic Retrieval | sentence-transformers, Chroma/ChromaDB, embeddings | Build a semantic search index for docs |
| RAG Pipelines | Retrieval + generation patterns | Create context-conditioned generation pipelines |
| Graph-based Agents | StateGraph primitives, memory & reasoning | Implement stateful agents that maintain context |
| Advanced & Production | Tool integrations, observability, safety | Extend workflows for real-world deployment |
First steps — verify your environment
Before you run labs, activate your virtual environment and ensure required packages are installed. Typical packages used in these labs include langchain, chromadb, sentence-transformers, numpy, and related dependencies.
Run this simple verification command after activating your venv:
```bash theme={null}
# Example: activate your virtualenv (update path if your venv is elsewhere)
source /root/venv/bin/activate && python /root/code/verify_environment.py
```
Make sure your virtual environment is activated before running verification or lab scripts. If you created the venv in a different path, update the `source` command to point to your activate script.
Tools, libraries, and resources
* LangChain — orchestration of prompts and chains
* ChromaDB / Chroma — lightweight vector database options
* sentence-transformers — high-quality embedding models
* numpy — numerical operations for preprocessing
* Additional tooling: Docker, cloud object stores, monitoring/observability tools (for advanced labs)
Vector databases and semantic search
Vector databases let you store and query embeddings so retrieval is based on semantic similarity instead of keyword matches. In this course you’ll create a semantic search engine for technical documentation, then use embeddings to retrieve relevant passages for downstream tasks.
Key steps in a semantic search pipeline
1. Ingest documents (split into passages / chunks).
2. Compute embeddings with a suitable encoder (e.g., sentence-transformers).
3. Store embeddings in a vector store (ChromaDB, FAISS, Milvus, etc.).
4. Query by embedding for nearest neighbors, then re-rank or filter before use.
Retrieval-Augmented Generation (RAG)
RAG pipelines first retrieve relevant context and then condition a generative model on that context. This reduces hallucination and improves factuality by grounding the model’s responses in retrieved documents.
Common RAG flow:
* User query → embedding → nearest-neighbor documents → concat or summarization → conditioned generation
Verifying package installation (sample pip output)
When installing Python packages you may see output confirming dependencies are already satisfied in your virtual environment. Example pip output:
```console theme={null}
Requirement already satisfied: watchfiles>=0.13 in ./venv/lib/python3.12/site-packages (1.1.0)
Requirement already satisfied: websockets>=10.4 in ./venv/lib/python3.12/site-packages (15.0.1)
Requirement already satisfied: humanfriendly>=9.1 in ./venv/lib/python3.12/site-packages (10.0)
Requirement already satisfied: MarkupSafe>=2.0 in ./venv/lib/python3.12/site-packages (3.0.3)
Requirement already satisfied: oauthlib>=3.0.0 in ./venv/lib/python3.12/site-packages (3.3.1)
Requirement already satisfied: joblib>=1.2.0 in ./venv/lib/python3.12/site-packages (1.5.2)
Requirement already satisfied: threadpoolctl>=3.1.0 in ./venv/lib/python3.12/site-packages (3.6.0)
```
Then run the verification script:
```bash theme={null}
python3 /root/code/verify_environment.py
```
Building stateful agents with a graph-based approach
Graph-based workflows allow agents to maintain state across steps, support structured messaging, and enable multi-step reasoning. These primitives are useful when agents must remember past interactions, update state, and decide next actions conditionally.
Example: imports and a simple message field (excerpt)
```python theme={null}
# /root/code/task_1_understanding_imports.py (excerpt)
from langgraph.graph import StateGraph, END
from typing import TypedDict
# Example field that will hold messages in this workflow
messages: list
```
Run the import verification and view the script:
```bash theme={null}
python3 /root/code/task_1_understanding_imports.py
```
Advanced topics and production considerations
In advanced labs you will:
* Integrate external tools (APIs, databases, search) into graph workflows.
* Add observability and logging for debugging and auditing agent behavior.
* Apply safety patterns and guardrails (rate limits, input sanitization, rejection sampling).
* Compose multi-step flows and orchestrate complex agent behavior suitable for production.
Links and references
* LangChain: [https://docs.langchain.com/](https://docs.langchain.com/)
* Chroma (ChromaDB): [https://www.trychroma.com/](https://www.trychroma.com/)
* sentence-transformers: [https://www.sbert.net/](https://www.sbert.net/)
* Retrieval-Augmented Generation (overview): [https://en.wikipedia.org/wiki/Retrieval-Augmented\_Generation](https://en.wikipedia.org/wiki/Retrieval-Augmented_Generation)
Conclusion
This course equips you to go from a single API call to complete, stateful AI agents that perform semantic retrieval, grounded generation, and multi-step reasoning. Follow the hands-on labs to verify your environment, build a semantic search index, implement RAG pipelines, and design graph-based agents that persist state and make informed decisions.
Whether you are starting out or deepening your skills, the practical examples and lab exercises will help you build and deploy robust AI-driven applications.
# Claude API Overview
Source: https://notes.kodekloud.com/docs/AI-Agents/API-Integrations-Tools/Claude-API-Overview/page
Overview of Anthropic's Claude API, its design, models, message-based interface, tools, file handling, and agent best practices.
Welcome back.
This lesson provides a structured overview of Claude: its design philosophy, common use cases, the Claude Messages API and key endpoints, message roles and prompt structuring, tool/function calling, agent capabilities, code and file handling features, model variants, rate limits and pricing considerations, and best practices for integrating Claude into agent systems.
Overview: Claude in context
Claude is a production-grade, safety-first large language model from Anthropic that focuses on steerability, alignment, and reliable multi-turn behavior. Its API is designed to integrate with agent pipelines and conversational applications — supporting long-context reasoning, structured tool use, and file interactions that are essential for automation and developer workflows.
Key strengths and agent capabilities
Claude excels in nuanced instruction-following, long-document understanding, and multi-step reasoning. These capabilities make it a strong choice for agents that must read large documents, summarize complex reports, execute multi-stage tasks, or work with external tools and APIs. Claude’s design emphasizes safety and alignment, so it is well-suited for higher-stakes or regulated environments.
Background and alignment
Claude is Anthropic’s flagship conversational and assistive AI model, named after Claude Shannon in homage to information theory and structured reasoning. It is trained with techniques that emphasize safety and self-consistency, notably Constitutional AI, which helps the model critique and refine its outputs against a set of guiding principles.
Design philosophy and common use cases
Claude is engineered to be helpful, honest, and harmless. Its strengths include steerability (prompt-driven behavior control), debuggability (more traceable reasoning), and robust instruction-following — useful for applications like document parsing, coding assistance, conversational agents, and autonomous agent workflows.
Examples of practical applications
* Document parsing and extraction (financial reports, contracts)
* Pair programming and code review automation
* Long-form summarization and multi-turn conversational assistants
* Agent pipelines that perform planning, tool execution, and verification
Models and the message-based API
Anthropic exposes several Claude model families (for example, Opus, Sonnet, and Haiku). Claude’s API is message-first: you send a sequence of messages (system, user, assistant) and receive assistant responses. This mirrors chat-style interactions and maps cleanly to agent workflows where context and roles are important.
Primary endpoint
The main HTTP endpoint for the message-based API is:
* POST `/v1/messages`
This endpoint accepts system-level instructions, user prompts, and optional tool or file references. It supports streaming responses and is designed for multi-turn, stateful interactions.
Example: calling the Claude Messages API
Below is a minimal Python example demonstrating the message format used by the Messages API via a direct HTTP call. Replace `ANTHROPIC_API_KEY` with your key or use your preferred SDK for additional features like retries and streaming.
```python theme={null}
# python
import os
import requests
API_KEY = os.environ.get("ANTHROPIC_API_KEY", "my_api_key")
URL = "https://api.anthropic.com/v1/messages"
payload = {
"model": "claude-3-7-sonnet-20250219",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Hello, Claude"}
]
}
headers = {
"x-api-key": API_KEY,
"Content-Type": "application/json"
}
resp = requests.post(URL, json=payload, headers=headers)
resp.raise_for_status()
print(resp.json())
```
Message roles and structuring
Claude uses role-attributed messages that help maintain consistent behavior across a conversation. Use role separation to improve predictability and control.
| Role | Purpose | Example |
| ----------- | ----------------------------------------------------- | -------------------------------------------------------------------- |
| `system` | Sets persona, global constraints, and output format | `You are an expert research assistant. Be concise and cite sources.` |
| `user` | End-user inputs, questions, or task prompts | `Summarize this report and extract key metrics.` |
| `assistant` | Model-generated output (sent by the API in responses) | Generated content from the model |
Use a system message to define persona, constraints, and output format. This improves reliability, especially in agent pipelines.
Tool use and function calling
Claude supports structured function calling (tool use). Define tools with explicit parameter schemas so the model can safely decide when to call them. Typical tools include external APIs, database queries, calculators, or custom utilities. Use tight JSON schemas to reduce ambiguity and simplify downstream execution and verification.
Code, files, and Claude Code features
Claude Code extends Claude’s abilities for code reasoning and file interactions. You can upload files (PDF, CSV, code files) and reference them by ID in messages. Claude can parse, summarize, extract structured data, or run code analysis on uploaded artifacts.
Use cases:
* Extract tabular data from financial PDFs
* Perform QA across long documents
* Review source code and suggest fixes
Files are handled as persistent objects, allowing agents to operate over them repeatedly without re-uploading.
Model variants: Opus, Sonnet, Haiku
Choose a Claude model based on capability, context window size, latency, and cost trade-offs:
| Model | Best for | Notes |
| ------ | ------------------------------------------ | --------------------------------------------------------------------------------- |
| Opus | Highest capability and very large contexts | Suitable for massive documents and complex reasoning (very large context windows) |
| Sonnet | Balanced capability and cost | Good general-purpose option for many agent tasks |
| Haiku | Low-latency, cost-efficient | Optimized for short chats and high-throughput scenarios |
All models typically support streaming responses and batching. Select the model based on your workload, latency budget, and cost constraints.
Pricing and limits
Pricing and rate limits vary by model and account tier. Monitor token usage, request rates, and latency, particularly with large-context models like Opus. Use caching, summarization of long histories, and context window management to control costs and maintain performance.
Best practices for agent architectures
* Use a strong system message to define persona, format, and constraints.
* Keep roles separated (system vs user) to reduce prompt drift.
* Define tools with strict parameter schemas and validation.
* Prefer streaming and batching to reduce perceived latency in real-time apps.
* Implement caching and summarization to manage long-term context without exceeding token limits.
* Monitor token usage and latency; choose models according to workload needs.
How Claude compares to other LLM APIs
Claude differs from other providers (for example [OpenAI GPT-4](https://openai.com/product/gpt-4) and [Google Gemini](https://blog.google/technology/ai/introducing-gemini/)) in several important ways:
* Constitutional AI: Claude emphasizes internal critique and rule-guided behavior, which supports safer outputs compared with purely RLHF approaches.
* Native tool and file support: Claude provides built-in file handling and structured function calling, reducing the need for separate plugin layers.
* Message-first interface: The messages-based design maps naturally to agent architectures and long multi-turn workflows.
While other providers may excel at ecosystem integrations or cloud-native services, Claude is particularly well-suited for safety-sensitive, agent-driven deployments that require robust alignment, long-context handling, and integrated tool/file interaction.
Links and references
* Anthropic: [https://www.anthropic.com](https://www.anthropic.com)
* Claude Shannon (background): [https://en.wikipedia.org/wiki/Claude\_Shannon](https://en.wikipedia.org/wiki/Claude_Shannon)
* Constitutional AI (Anthropic blog): [https://www.anthropic.com/blog/constitutional-ai](https://www.anthropic.com/blog/constitutional-ai)
* OpenAI GPT-4: [https://openai.com/product/gpt-4](https://openai.com/product/gpt-4)
* Google Gemini announcement: [https://blog.google/technology/ai/introducing-gemini/](https://blog.google/technology/ai/introducing-gemini/)
# Demo How to Use Claude API
Source: https://notes.kodekloud.com/docs/AI-Agents/API-Integrations-Tools/Demo-How-to-Use-Claude-API/page
Tutorial for building a minimal Claude chat agent in Jupyter using the Anthropic Python SDK with installation, API key setup, code example, and troubleshooting tips.
Welcome back! In this lesson you'll learn how to create a minimal Claude-based chat agent in a Jupyter notebook using the official Anthropic Python package. Claude is a capable assistant for text and code tasks — it produces natural writing, has strong coding abilities, supports artifacts for visualization, and offers thoughtful analysis. That makes it a good fit for developers, writers, and analysts building interactive demos, research tools, or content assistants.
Before you begin, review the official docs at [docs.anthropic.com](https://docs.anthropic.com) to see available models, capabilities, and up-to-date API patterns and examples. The documentation lists models such as Claude Opus and Claude Sonnet and provides versioned guidance for SDK usage.
Get started by opening a new notebook (for example, name it "ClaudeDemo") and follow the steps below.
## Prerequisites
* Python 3.8+ (or a supported version for your `anthropic` SDK)
* A Claude API key from Anthropic
* Basic familiarity with Jupyter notebooks
## Installation
Install the official Anthropic package from PyPI:
```bash theme={null}
!pip install anthropic
```
## Setting the API Key
Store your Claude API key securely — the recommended approach is an environment variable such as `CLAUDE_API_KEY`. For quick demos you can use a placeholder or local config, but never commit real keys.
Never commit API keys or other secrets to public repositories. Use environment variables, a secrets manager, or platform-provided secret stores in production.
Be aware of usage limits and billing. Running long conversations or repeated calls can incur cost—monitor your Anthropic account and set safeguards where appropriate.
## Minimal Claude Chat Agent (single Python cell)
The example below demonstrates a compact pattern for a Jupyter cell that:
* Initializes the Anthropic client,
* Sends a system-level prompt to define the assistant behavior,
* Maintains short-term message history,
* Runs an interactive loop for chatting.
Copy the whole block into a single notebook cell and run it.
```python theme={null}
# python
import os
import anthropic
# Prefer environment variable; replace with a secure source in real projects.
CLAUDE_API_KEY = os.environ.get("CLAUDE_API_KEY", "")
# Initialize client
# Depending on the SDK version this may be `anthropic.Client(...)` or `anthropic.Anthropic(...)`.
client = anthropic.Anthropic(api_key=CLAUDE_API_KEY)
# System prompt defines the assistant's role/personality.
system_prompt = "You are a helpful research assistant. Answer clearly and concisely."
# Short-term chat history (list of {"role": "user" | "assistant", "content": str})
message_history = []
def run_claude_agent(message_history, user_input):
"""
Append the user input to the message history, send the conversation
(with system prompt) to Claude, append the assistant reply to history,
and return the assistant reply.
"""
# Add user message to history
message_history.append({"role": "user", "content": user_input})
# Send request to Claude
response = client.messages.create(
model="claude-3-opus-20240229",
max_tokens=500,
temperature=0.7,
system=system_prompt, # Some SDKs take system separately; follow your SDK docs
messages=message_history # messages should use "user" and "assistant" roles
)
# Extract assistant text from response.
# SDK response formats vary between versions; try common patterns.
assistant_reply = ""
if hasattr(response, "content") and len(response.content) > 0:
first = response.content[0]
# Some SDKs return objects with a 'text' attribute or dicts with 'text'
assistant_reply = getattr(first, "text", None) or (first.get("text", "") if isinstance(first, dict) else str(first))
else:
# Fallback: represent the raw response
assistant_reply = str(response)
# Add assistant reply to history and return
message_history.append({"role": "assistant", "content": assistant_reply})
return assistant_reply
# Interactive chat loop
if __name__ == "__main__":
print("Start chatting with the Claude agent. Type 'exit' or 'quit' to end.")
while True:
user_input = input("You: ").strip()
if user_input.lower() in ["exit", "quit"]:
print("Exiting Claude agent, goodbye!")
break
reply = run_claude_agent(message_history, user_input)
print("\nClaude:", reply, "\n")
```
## Key implementation notes
* Many Anthropic SDKs accept a separate `system` parameter instead of a message with `"role": "system"`. If you include a `"system"` role inside `messages` when the SDK expects a `system` parameter, you may see errors. Always consult the documentation for the SDK version you're using.
* Use `"user"` and `"assistant"` roles in the `messages` list to preserve conversation state and allow Claude to reference earlier turns.
* Tune `max_tokens` to control the maximum reply length and `temperature` to adjust randomness.
* SDK class and method names may change between versions — e.g., `anthropic.Client` vs `anthropic.Anthropic`. If you encounter import errors or an unexpected response structure, check [docs.anthropic.com](https://docs.anthropic.com) for version-specific examples.
## Quick reference: common troubleshooting
| Symptom | Likely cause | Quick fix |
| -------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------- |
| ImportError on `anthropic` | Package not installed or wrong environment | Run `!pip install anthropic` in the notebook kernel and restart kernel |
| Authentication error | Missing or invalid API key | Ensure `CLAUDE_API_KEY` env var is set; avoid committing credentials |
| Unexpected response format | SDK version differences | Print `response` to inspect structure and adapt parsing; consult SDK docs |
| SDK method not found | Version mismatch | Check release notes or use the version documented on [docs.anthropic.com](https://docs.anthropic.com) |
## Try it out
After starting the interactive loop, try asking Claude a question such as:
* "Give me a recipe for banana bread."
* "Summarize the key points from this paragraph."
* "Draft a short email asking for a meeting."
The notebook will display the assistant's reply and preserve the chat history so Claude can use earlier context. Type `exit` or `quit` to end the session.
## Extending the agent
From this minimal example you can extend your agent in many ways:
* Persist chat history to disk or a database for longer-term context.
* Add tools or retrieval layers (e.g., vector DB + semantic search) to ground responses in external data.
* Implement streaming responses (if supported by your SDK) for real-time UI updates.
* Post-process model outputs to extract structured data, generate artifacts (tables, charts), or call downstream APIs.
## Wrapping up
This guide demonstrated a minimal Claude chat agent in a Jupyter notebook:
* Define a system role to shape behavior.
* Maintain a message history to give Claude conversational context.
* Send the system prompt and messages via `client.messages.create`.
* Append assistant replies to history.
* Use an interactive loop to simulate chat sessions.
Next steps: explore the model and SDK options in the Anthropic docs, experiment with different system prompts for specialized behavior, and add retrieval or post-processing layers to build more capable assistants.
## Links and references
* Anthropic documentation: [https://docs.anthropic.com](https://docs.anthropic.com)
* Anthropics Python package on PyPI: [https://pypi.org/project/anthropic/](https://pypi.org/project/anthropic/)
# Demo How to Use Poe
Source: https://notes.kodekloud.com/docs/AI-Agents/API-Integrations-Tools/Demo-How-to-Use-Poe/page
Guide to using Poe to build, test, embed, and monetize conversational AI bots with server and embedded options, UI walkthrough, and integration guidance
Welcome back.
In this lesson we’ll walk through how to use Poe (Platform for Open Exploration) — Quora’s chatbot platform — to create, test, and embed conversational AI agents. This guide covers the core capabilities, the user interface, a quick hands-on demo to build a prompt bot, and links to further documentation.
What is Poe?
Poe is a chat-first platform that lets you interact with powerful large language models (LLMs) such as GPT-4, Claude, and others via a polished chat UI. Poe supports:
* Server bots: you host the backend logic and Poe provides the front-end chat experience.
* Embedded bots: embed a Poe widget into your web app or notebook.
* Creator features: monetization and subscription options for bot creators.
What Poe can do
* Build server bots: Host your backend LLM, call external APIs and tools, manage conversation state, and stream multi-message responses while Poe handles the chat UI.
* Embed bots: Use Poe’s embed API to place bots in websites, apps, or dashboards. Any bot you publish on Poe can be embedded and customized.
* Monetize: Optional creator monetization and subscription controls let you charge for access or messages.
Feature summary
| Capability | Use case | Quick example |
| --------------- | ------------------------------------------ | -------------------------------------------------------- |
| Server bots | Custom backend, tools, APIs | Host your own LLM and stream responses to Poe’s frontend |
| Embedded widget | Add a chat UI to a website or SaaS product | Embed a bot with a few configuration options |
| Monetization | Charge users or set message limits | Enroll in Poe’s creator program and set message prices |
Explore the UI
The Poe interface makes it easy to create different bot types — prompt bots, image/video generation bots, roleplay bots, server bots, and canvas apps. The left navigation groups your bots, subscriptions, and settings so you can manage projects and billing in one place.
You can also browse available LLMs (e.g., Claude, Gemini, GPT-4 variants) and review creator-focused features such as monetization settings and enrollment options.
Quick walkthrough — create a simple prompt bot
This step-by-step example demonstrates how fast it is to set up a prompt bot and test its behavior.
1. Click Create and choose “Prompt bot.”
2. Enter a name (for example: “Teach Me Many Things”).
3. Add a description and a persona/system instruction. Example:
* “You are a Poe bot that will teach me how to code. You should respond as thoroughly as possible, but always speak as if you are Jar Jar Binks.”
4. Choose a base model (for example, GPT-4 or a lightweight GPT-4 variant).
5. Optionally add an initial message such as “Hi there, how can I help?”
6. Review advanced settings (keep defaults for this demo) and click Publish → Continue without editing.
Test the bot
After publishing, test the bot in Poe’s chat interface. For this demo we asked:
“Can you teach me how to make a grilled cheese sandwich?”
The bot returned a step-by-step recipe while adhering to the specified persona, showing how system instructions influence tone and content.
Integration options
* Embed: Use Poe’s embedded API to include the chat widget in web apps or notebooks.
* Server API: Connect a backend to Poe’s RESTful endpoints to send/receive messages, stream responses, and manage conversation state.
* Tools & APIs: Integrate external APIs and tools on your hosted backend for richer agent capabilities.
Before integrating or publishing bots, review Poe’s documentation for API usage, authentication, rate limits, and billing. Keep your API keys secret and follow security best practices when embedding or hosting bots.
Next steps and references
* Read Poe’s Quick Start and API docs for authentication, generating API keys, and handling streaming responses: [https://poe.com/docs](https://poe.com/docs)
* Explore sample projects and community examples to learn advanced patterns like tool integration and multi-step pipelines.
That’s a concise introduction to building, testing, and embedding bots on Poe. Explore the documentation and try creating a few bot personas to understand how system instructions and model selection shape responses.
# Kubernetes MCP
Source: https://notes.kodekloud.com/docs/AI-Agents/API-Integrations-Tools/Kubernetes-MCP/page
Explains Kubernetes Multi-Cluster Proxy (MCP) for securely connecting and routing services across distributed, multi-cluster AI agent infrastructures, covering architecture, deployment, security, and best practices.
Welcome back.
In this lesson we'll cover Kubernetes MCP (Multi-Cluster Proxy) and how it helps connect distributed AI agent infrastructure across clusters, regions, and air-gapped environments.
Topics covered:
* What Kubernetes MCP is and why it matters for AI agent infrastructure
* Core architecture: servers, clients, proxies, and tunnels
* MCP server and client interaction
* How MCP enables distributed AI agents and secures AI workflows across clusters
* Use cases and an MCP vs. traditional load balancer comparison
* Deploying MCP with Helm and Kubernetes
* Best practices for AI agent scaling with MCP
* Limitations and monitoring considerations
As agent-based systems grow in scale and complexity, they often need to operate across multiple clusters, regions, or isolated networks. Kubernetes MCP — Multi-Cluster Proxy — provides secure, tunneled connectivity between clusters, enabling cross-cluster routing and real-time interactions without exposing internal services to the public internet. For teams building large-scale or enterprise AI systems, understanding MCP is essential for secure, scalable, and cost-effective deployments.
Problem statement: in traditional Kubernetes architectures, clusters are isolated by default. Exposing services across regions or to other clusters typically requires complicated network changes, VPNs, or public endpoints. MCP addresses these challenges by creating persistent, secure tunnels from MCP clients (deployed alongside your services) back to a central MCP server. This avoids redesigning cluster networking and reduces the need to expose internal services publicly — a pattern that fits hybrid cloud, multi-region, and air-gapped use cases.
By acting as a central routing layer, MCP enables services in one cluster to securely access services in another — databases, internal APIs, or LLM inference endpoints — without changing cluster networking. In AI agent ecosystems, components (memory stores, inference services, orchestrators) are often distributed for cost, latency, or compliance reasons. MCP lets these components interoperate across cluster boundaries while preserving security and minimizing operational changes.
This architecture makes it easy to colocate GPU-accelerated inference in one cluster, run orchestration or planning agents in another, and host sensitive data in a locked-down region — all while maintaining low-latency, secure access between them.
Core architecture overview
| Component | Role |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| MCP server | Central routing hub (typically in a hub/central cluster). Maintains registry of available services and active client tunnels. |
| MCP client (agent) | Runs in satellite/remote clusters. Opens and maintains a persistent secure tunnel to the MCP server and registers local services to proxy. |
| Service registration | Mechanism for clients to announce which local services (internal APIs, vector DBs, LLM endpoints) are reachable via the tunnel. |
| Tunnel transport | Persistent WebSocket connections (wss\://) or similar secure channels used to route traffic bidirectionally. |
When a client or external host needs access to a registered service, the MCP server routes the request down the correct tunnel to the target client; responses are returned the same way. This enables cross-cluster communication without exposing internal IPs or creating a full mesh.
Common deployment pattern
A typical pattern is a client–server model:
* Host application (IDE, agent runtime, or developer tool) runs an MCP client and talks to one or more MCP servers.
* Each MCP server connects to local data sources and may also proxy requests to remote web APIs.
* Hosts pull context or data from multiple clusters in real time, supporting decentralized data integration and task coordination.
MCP interactions (high-level flow)
When a client starts:
1. Opens a secure WebSocket tunnel to the MCP server (commonly `wss://`).
2. Authenticates (mTLS, tokens, or platform-specific mechanisms).
3. Registers the services it can proxy.
4. Listens for proxied requests forwarded by the server and routes them to local services.
Requests from other clients or from the server travel via the MCP server and the selected client tunnel to the destination service; responses flow back through the same path. This design provides secure, bidirectional routing across clusters.
Why MCP matters for AI agent systems
Modern AI agent ecosystems are distributed by design:
* Inference often runs on GPU-optimized clusters.
* Memory/knowledge stores may be placed in specific regions for compliance.
* Planners or orchestrators can run in secure zones.
MCP maintains separation of concerns while providing low-latency, secure access between these components. Instead of implementing complex network policies across clusters, MCP handles discovery and routing at the application layer.
Security considerations
* Encrypt all tunnels (wss/TLS).
* Use authentication: mutual TLS (mTLS) or token-based authentication to authorize clients.
* Apply IP allow-listing and RBAC at the MCP server to restrict reachability of registered services.
* Never expose sensitive services directly to the public internet; prefer tunneled access through MCP.
For regulated environments (healthcare, finance, defense), pair MCP with strict certificate lifecycle management, centralized audit logging, and least-privilege service definitions to meet compliance and audit requirements.
Real-world use cases
* Research agents in one region accessing production-only services in a separate region without making those services public.
* Dedicated GPU clusters exposing LLM inference endpoints locally while orchestration agents run in other clusters.
* Edge devices (robots, appliances) creating secure tunnels back to a centralized planner in a hub cluster.
MCP vs. traditional load balancers
| Aspect | Load Balancer | Kubernetes MCP |
| ---------- | ----------------------------------------------- | ------------------------------------------------------------------------------ |
| Scope | Distributes traffic within a region/VPC/cluster | Cross-cluster service discovery and secure routing |
| Use case | Horizontal scaling, HA within same network | Tunneling and connecting isolated clusters/air-gapped environments |
| Exposure | Often requires public endpoints or VPNs | Preserves internal-only services via secure tunnels |
| Complexity | Well-supported for HTTP/TCP balancing | Adds tunneling layer and service registry; better for autonomy across clusters |
Use a load balancer for intra-cluster or single-cloud scaling. Use MCP when you need cross-cluster autonomy, secure multi-cluster orchestration, or to connect air-gapped/satellite clusters.
Deploying MCP with Helm (high-level steps)
1. Deploy MCP server into a central/hub cluster.
2. Deploy MCP clients into satellite clusters and configure them to connect to the server.
3. Define which services to expose using Kubernetes-native objects (Service, ConfigMap, or CRDs if provided by the MCP implementation).
4. Verify tunnels and the service registry, then test end-to-end routing.
Example Helm commands (replace placeholders with your values):
```bash theme={null}
# Add chart repo and update
helm repo add mcp https://charts.example.com/mcp
helm repo update
# Install MCP server in a hub cluster
helm install mcp-server mcp/mcp-server --namespace mcp-system --create-namespace
# Install an MCP client in a satellite cluster and point it at the server
helm install mcp-client mcp/mcp-client --namespace mcp-client --create-namespace \
--set server.url="wss://mcp-server.example.com" \
--set server.auth.token="YOUR_TOKEN_HERE"
```
After installation, confirm client tunnels and service registrations using kubectl and your MCP server status endpoints:
```bash theme={null}
kubectl get pods -n mcp-system
kubectl get pods -n mcp-client
# Check registered services (implementation-specific)
kubectl get services -A
```
Best practices for operating MCP at scale
* Separate agents by role and region. Keep memory, inference, and control agents in different clusters based on operational needs.
* Avoid exposing sensitive services directly; always prefer tunneled access via MCP.
* Monitor tunnel health and connection metrics. Latency spikes or dropped tunnels directly affect agent performance.
* Integrate MCP logs and metrics into your observability stack (Prometheus, Grafana, EFK/ELK) to trace cross-cluster requests and speed up debugging. See Learn By Doing: AIOps Foundations - Intelligent Monitoring With Prometheus & Grafana and EFK Stack: Enterprise-Grade Logging and Monitoring.
* Document service ownership per cluster to prevent overlap and ensure predictable routing.
Limitations and monitoring considerations
* Latency: Tunneling adds overhead. For high-frequency, low-latency workloads, measure end-to-end latency and consider colocating tightly-coupled components.
* Tunnel health: If a WebSocket tunnel drops, agent communication fails. Implement robust reconnection logic and active health checks.
* Debugging complexity: Cross-cluster flows are multi-hop. Centralize logs and traces to reconstruct interactions across clusters.
* Autoscaling: Many MCP implementations don’t auto-scale proxies out-of-the-box. Integrate with existing orchestration/autoscaling tools to handle load surges.
Monitor tunnel availability and end-to-end latency closely. For latency-sensitive inference, evaluate colocating inference components or using dedicated low-latency links rather than relying solely on cross-cluster tunnels.
Wrap-up
Kubernetes MCP is a practical solution for connecting distributed AI agents across clusters and network boundaries while preserving security, modularity, and deployment autonomy. With proper observability, authentication, and deployment hygiene, MCP simplifies multi-cluster AI architectures and enables teams to place services where they are most effective. For production-grade setups, combine MCP with strong certificate management, centralized logging/tracing, and an automation strategy for scaling and failover.
# Manus AI Overview
Source: https://notes.kodekloud.com/docs/AI-Agents/API-Integrations-Tools/Manus-AI-Overview/page
Overview of Manus AI, an open source agent operating system for building persistent, long‑horizon agents with world models, durable memory, planning, tool integration, and observability
This lesson explains Manus AI — an open-source framework and operating-model for building persistent, long-horizon AI agents. Key topics covered:
* What Manus AI is and its core mission
* How Manus is architected and its main components
* Feature set and agent capabilities
* Manus as an AI operating system (OS) for long-running agents
* Interoperability with LLMs and external tools
* Developer experience, observability, and example configuration
* Practical use cases and real-world applications
* How Manus compares to other agent platforms
* Limitations, risks, and future directions
Manus represents a conceptual shift: treat agents as long-running, process-driven entities with persistent memory, planning loops, and explicit world-state models. It exposes system-level APIs that mirror operating-system patterns for coordinating resources — useful for developers building adaptive, persistent AI services rather than one-off prompt pipelines.
## What is Manus?
Manus is a full-stack, open-source framework tailored to build intelligent, persistent agents — not just another orchestrator or prompt wrapper. It behaves like an operating system for agents, designed for continuous adaptation and long-horizon planning.
The design draws inspiration from cognitive cycles: reflect → remember → act → adapt. Manus agents run over extended timeframes (hours to weeks) by using:
* persistent, vector-backed memories,
* structured planners and execution graphs,
* evolving world models.
This approach departs from reactive prompt-chaining toward agents that can reflect on prior actions, replan, and change behavior over time.
## Mission: world modeling and persistent cognition
Manus reframes agents as thinking systems rather than stateless tools. Agents maintain internal world models that are continuously updated as conditions change. Core design goals include:
* Long-running persistence across sessions
* Durable memory that survives restarts
* Primitives for constructing and evolving world models
* Structured autonomy via tool selection and API calls
These capabilities make Manus suitable for applications that need continuous context, historical awareness, and goal-directed autonomy.
## Architecture and core components
Manus is modular around a central execution graph that models agent behavior as a network of planned steps and decision points. The canonical Manus cycle is: observe → plan → act → reflect. Main components include:
* Execution graph (planner + execution + verification)
* Persistent memory (vector-backed long-term store)
* Tool integration layer (abstracted external actions)
* World-state manager (evolving internal model)
* Observability/tracing components
A typical multi-agent pattern separates responsibilities:
* Planner agent: decomposes goals into tasks
* Execution agent: performs actions and calls tools
* Verification agent: checks outcomes and triggers corrections
This separation enables automated feedback loops and continuous improvement.
## Key features — what Manus provides
Manus elevates agents beyond single-shot generation by providing:
* World modeling: persistent, evolving internal representations of environments and entities
* Memory abstraction: retrievable long-term context that endures restarts
* Embodied planning: decisions that combine objectives, memory, and environment state
* Time-aware planning: schedule-aware reasoning over hours, days, or weeks
These primitives enable durable workflows, adaptive behavior, and richer automation patterns.
## Manus as an AI operating system
Manus treats agents as first-class processes: pause, resume, delegate, and hand off tasks across agents or services. At a system level, Manus exposes APIs to:
* Manage agent lifecycle and state
* Read/write persistent memory
* Register and call tools or external APIs
* Trace execution and observe agent decisions
This OS-like approach supports delegation, concurrency, lifecycle management, and event-driven behavior — useful for building interoperable, long-lived AI services.
## Interoperability with LLMs and external tools
Manus is model-agnostic and separates reasoning from tool execution. Typical setup:
* LLMs (e.g., Claude, GPT-4, Mistral, LLaMA) provide inference and planning guidance
* Tools (APIs, browser automations, local plugins) are abstracted into callable modules
* Runtime selects tools dynamically based on planner decisions
This reduces brittle prompt engineering and enables composable workflows where LLMs focus on reasoning and the Manus runtime handles execution and integration.
## Developer experience, observability, and example configuration
Manus provides a Python implementation and is distributed under an open-source license. Developers declare agents with declarative configuration files to improve reproducibility and version control. Observability features include logging, state tracing, and debugging tools that fit typical DevOps workflows.
Example minimal agent declaration (YAML):
```yaml theme={null}
agent:
id: research-assistant
roles:
- planner
- executor
memory:
backend: vector_db
vector_store: weaviate
tools:
- name: web_search
type: api
endpoint: "https://api.example-search.com/v1/query"
schedule:
run_interval: "1h"
```
Use declarative agent configs for reproducibility. Store them in Git and pair with CI/CD to control agent versions and rollout.
Observability and telemetry help monitor agent health, trace decision paths, and audit tool usage — essential for production deployments.
## Typical use cases
Manus excels in scenarios that require sustained planning and memory:
* Research assistants that replan experiments over time
* Product/design agents that track decisions across a project lifecycle
* Autonomous QA agents that adapt testing strategies as the codebase evolves
* AI DevOps agents that monitor infrastructure, schedule interventions, and collaborate with other agents
Other applications: data extraction, travel planning, comparative analysis, supplier sourcing, e-commerce optimization, financial reporting, education tools, and market research.
## Manus vs. other agent frameworks
The table below summarizes differences between Manus and typical prompt-chain frameworks (example: LangChain).
| Area | Manus | Stateless/Prompt-chain Frameworks |
| ------------- | --------------------------------------------------- | -------------------------------------- |
| Primary focus | Persistent autonomy, world models, execution graphs | Rapid prototyping, stateless chains |
| Memory | Vector-backed, durable memory primitives | Often session-scoped or ephemeral |
| Architecture | Execution graph + multi-agent roles | Linear or DAG prompt flows |
| Observability | Built-in tracing & lifecycle APIs | Varies by implementation |
| Extensibility | Tool abstraction + plugin model | Tools via connectors, but often ad-hoc |
For a broader introduction to prompt-chain tools, see [LangChain docs](https://learn.kodekloud.com/user/courses/langchain).
## Limitations, risks, and operational considerations
Manus is powerful but early-stage. Key concerns when adopting Manus:
* Engineering complexity: stateful services, distributed components
* Infrastructure cost: vector DBs, persistent stores, monitoring
* Security and governance: access control, data privacy, and auditing
* Safety: guardrails to prevent runaway or unsafe automation
Manus enables powerful, long-running agents, but with that power comes responsibility: design for observability, resource limits, access controls, and safe failover behavior to avoid runaway automation or data leakage.
## Future outlook and ecosystem
The Manus open-source ecosystem is maturing: contributions, plugins, and integrations are expanding. Roadmap directions include:
* Tighter simulation and robotics integration
* Symbolic reasoning modules and hybrid approaches
* Tooling for self-improving agents and automated fine-tuning
* Richer UI and management tooling for multi-agent orchestration
Over time, Manus may become a backend OS for multi-agent systems powering long-living AI assistants, real-time robotics, and complex automation platforms.
## Conclusion
Manus is a foundational framework for building agents that think, persist, and coordinate over time. For teams building adaptive, stateful agents, Manus offers primitives and architectural patterns that support long-term autonomy, observability, and modular reasoning. Adopting Manus requires investment in stateful infrastructure and governance, but it unlocks capabilities beyond short-lived prompt workflows.
## Links and references
* [LangChain documentation (example)](https://learn.kodekloud.com/user/courses/langchain)
* Vector DBs and memory stores: Weaviate, Pinecone, Milvus, Faiss
* Open-source agent frameworks and research papers (search for "long-horizon agents", "world modeling", "agent operating system")
# Poe Overview
Source: https://notes.kodekloud.com/docs/AI-Agents/API-Integrations-Tools/Poe-Overview/page
Overview of Quora's Poe platform for rapidly building, hosting, and integrating LLM-powered chatbots via webhook server bots, supporting multiple models, streaming, deployment, and design best practices.
Welcome back.
In this lesson we cover an overview of the Poe platform: what Poe is, why it matters, core use cases for Poe bots, the Poe API architecture and message flow, real-time streaming, creating custom bots, server-bot event types and message handling, LLM integrations (Claude, GPT, etc.), webhooks and hosting, best practices for Poe bot design, and limitations and comparisons with other platforms.
The Poe API from Quora is a fast way to build, test, and deploy AI-driven chatbots. It provides a hosted front end, supports multiple major models, and lets you concentrate on backend logic instead of maintaining full UI and infrastructure. For prototypes and MVPs, Poe reduces time-to-feedback and helps you iterate quickly.
## What is Poe?
Poe (Platform for Open Exploration) is Quora’s framework for creating and deploying chatbots powered by large language models (LLMs). Poe emphasizes accessibility: it provides a simple creator UI to connect models such as Claude, GPT-4, GPT-3.5, and others to real users while handling session management and the front end.
Key benefits:
* Hosted UI and session handling for faster prototyping
* Plug-and-play access to multiple LLMs
* Server-bot support for real-time backend logic and integrations
## Server-side bots and use cases
Poe’s server-side bots (webhook bots) let you implement real-time, agent-like behavior on your backend. These bots receive webhook events from Poe, execute logic, call APIs or external LLMs, and return structured JSON responses. Typical use cases include:
* Hosting and customizing LLM-powered chatbots without building a UI.
* Agentic bots that integrate with external APIs or run conditional, programmatic logic.
* Embedding conversational interfaces in web or mobile apps quickly.
* Rapid prototyping and iterative model testing before building a custom stack.
Poe’s webhook-based architecture keeps bots lightweight and largely stateless. Your server receives JSON event payloads, processes them, and returns a structured JSON response to control the conversation.
Because backend logic can call tools, external APIs, or other LLMs, Poe bots are not limited to static prompts. You can integrate reasoning, external knowledge, planning, tool usage, or persistence into the real-time chat experience.
## Typical request flow
A common request loop looks like this:
1. A user interacts with a client (web or mobile).
2. The client sends the message to Poe’s servers.
3. Poe routes the event to your configured server bot via HTTP POST.
4. Your server processes the event, optionally calling third-party APIs or LLMs (e.g., GPT-4 or Claude).
5. Your server returns a structured JSON response; Poe renders that response to the user.
This modular flow supports multi-bot interactions, dynamic orchestration on your backend, streaming tokens, and progressive message handling.
## Message loop and streaming
Poe sends an event payload (webhook) to your server whenever a user message arrives. Your server should return a valid JSON response within 30 seconds. Valid response types include:
* A complete message (single response)
* Streaming tokens (incremental partial responses)
* Suggestions or follow-up prompts
Streaming tokens reduce perceived latency for long outputs and can simulate real-time typing. For long-running tasks, begin streaming immediately and finalize when work completes.
## Creating a custom Poe bot
Start at the Poe Creator: [https://creator.poe.com](https://creator.poe.com). The creator UI lets you configure the bot’s display name, greeting, profile image, description, and the public webhook URL that receives Poe POSTs. You can also choose default LLM settings and session memory behavior.
Once configured, your server must handle the incoming webhook events and return responses per Poe’s schema.
## Server-bot event types and minimal response example
Server bots commonly receive these event types:
* `message` — user messages and conversation events
* `settings_update` — changes to bot configuration
* `report_feedback` — user feedback events
* `error` — diagnostic or error events
At minimum, handle `message` events and return a JSON object containing fields like `messages` or `text`. Here is a minimal response example:
```json theme={null}
{
"messages": [
{
"type": "message",
"text": "Hello! How can I help you today?"
}
],
"isFinalResponse": true
}
```
Optional fields such as `meta` or `stop` can be used to control flow more granularly (partial responses, fallbacks, or suggested actions).
## LLM integrations and model selection
Poe supports multiple models out of the box, including Claude 3, Claude Instant, GPT-4, GPT-3.5, Google PaLM, and Meta LLaMA 2. Choose models based on the task:
* Claude: steerable safety and structured responses
* GPT-4: creative, reasoning-heavy tasks
* Smaller/faster models: low-latency or cost-sensitive tasks
Poe handles front-end hosting and session management, while you control backend orchestration and tool integration.
## Webhooks, hosting, and deployment
Because Poe relies on webhooks, your backend must be publicly accessible over HTTPS and able to receive POST requests. Poe expects a JSON response within 30 seconds, so design for low latency or use streaming for long-running tasks.
Recommended hosting options:
* Render, Vercel, Replit, Glitch — lightweight platforms that provide HTTPS endpoints.
* Container platforms or cloud VMs if you need more control.
If you use frameworks such as Flask, FastAPI, or Express.js, implement a route to receive Poe POSTs, validate incoming payloads, and respond per the schema. Store API keys, LLM credentials, and secrets in environment variables to avoid hard-coded values. Add logging, monitoring, and robust error handling to manage malformed payloads or timeouts.
Your webhook endpoint must be publicly reachable over HTTPS and secured. Never commit API keys or secrets to source control — use environment variables, secret stores, or platform-provided secret management.
Keep synchronous responses under 30 seconds. For tasks that take longer, stream tokens immediately to improve perceived responsiveness.
## Best practices for Poe bot design
* Keep synchronous response latency below 30 seconds; stream for long-running tasks.
* Use Markdown formatting (bold, lists, links) to improve readability.
* Validate user input before invoking external APIs or performing actions.
* Test all event types and edge cases (errors, retries, feedback events) to ensure production reliability.
* Log requests/responses and implement retries and graceful degradation for third-party failures.
* Use rate limiting and quota controls for downstream APIs to prevent unexpected costs or throttling.
## Limitations and comparisons
Consider these limits when deciding whether Poe fits your product:
* The built-in UI is primarily a chat window with limited customization. If you need rich UI components, build a custom front end.
* Poe does not natively provide complex orchestration or tool-chaining like frameworks such as LangChain. Implement multi-agent or stepwise planners on your backend when needed.
* Because Poe controls hosting of the front end and UI, there are constraints compared to fully custom stacks — but Poe often speeds up prototyping and early-stage testing.
Comparison summary:
| Focus | Poe | Custom Stack (+LangChain) |
| --------------------------- | ---------------------------- | ---------------------------------------------------- |
| Front-end hosting | Included (chat UI) | Self-hosted/custom UI |
| Orchestration/tool-chaining | Backend-implemented | Can use orchestration frameworks (e.g., `LangChain`) |
| Speed to prototype | Fast | Slower (more infra) |
| Custom UI flexibility | Limited | Full control |
| Model selection | Built-in multi-model support | Depends on integrations you build |
## When to choose Poe
Poe is an excellent choice for early-stage projects, prototypes, or lightweight agent wrappers when you want to iterate quickly and test user interactions without building a full UI. For complex, high-control multi-agent systems, or deeply customized front ends, consider building a custom stack and using orchestration frameworks on your backend.
## Links and references
* Poe Creator: [https://creator.poe.com](https://creator.poe.com)
* LangChain (example orchestration framework): [https://langchain.com/](https://langchain.com/)
* Kubernetes Basics: [https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/](https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/)
Further reading:
* Poe docs (creator and webhook guides) — check the Poe creator site for the latest webhook schema and examples.
* Provider docs for any LLMs you integrate (OpenAI, Anthropic, Google, Meta) for model-specific guidance and authentication details.
# Audio AI Agent Speech Translator
Source: https://notes.kodekloud.com/docs/AI-Agents/Advanced-Agents-Projects/Audio-AI-Agent-Speech-Translator/page
Explains building speech translation agents that transcribe, detect languages, translate, and synthesize audio using OpenAI tools, covering architecture, streaming versus batch, use cases, and best practices.
Welcome back.
This lesson covers the Audio AI Agent — Speech Translator. You'll learn what a speech translation agent does, why audio input matters, the OpenAI audio tools available, the common architecture and data flow, streaming vs. batch trade-offs, memory/context integration, representative use cases, limitations and best practices, and a concise example flow you can adapt to your SDK or API.
We will cover:
* What a Speech Translation Agent is and why audio input matters
* OpenAI audio tools (WhisperInput and Text-to-Speech)
* The Speech Translator Agent architecture: capture → transcription → language detection → translation → output
* Transcription, language detection, and translation flow
* Output options (text vs. synthesized speech)
* Streaming vs. batch processing
* Integration with agent tooling and memory, use cases, and best practices
Audio AI agents enable voice-first, accessible, multilingual experiences. They let systems listen, understand, translate, and speak — unlocking natural human-AI dialogue in scenarios where typing is impractical (live meetings, kiosks, travel assistants, voice-first educational apps, accessibility aids, and more).
## What is a Speech Translation Agent?
A speech translation agent takes audio input, converts speech to text, detects the speaker’s language, translates into one or more target languages, and returns either translated text, synthesized speech, or both. It functions similarly to human interpreters and can be embedded into mobile assistants, contact centers, kiosks, and accessibility tools.
Typical capabilities:
* Real-time or batch transcription
* Language detection and context-aware translation
* Synthesized audio responses via TTS
* Integration with memory and tooling for continuity and personalization
## Why include audio input?
Voice input is essential when typing is inconvenient or impossible (hands-free scenarios, mobile usage, low literacy, or accessibility needs). Combined with transcription and translation, voice enables:
* Live multilingual assistants and meeting interpreters
* Faster, natural interactions (speak and listen like with a human)
* Multimodal workflows (speech + text + UI)
## OpenAI audio tools
OpenAI provides two primary audio building blocks commonly used in speech translation agents:
| Tool | Purpose | Notes |
| ------------------------ | -------------------------------------------- | ------------------------------------------------------------- |
| WhisperInput | Speech-to-text transcription | Supports MP3, WAV, M4A; available in file and streaming modes |
| Text-to-Speech (TTS) API | Synthesizes natural-sounding audio from text | Configurable voices, prosody, and locale options |
WhisperInput handles many languages and audio conditions; the TTS API lets agents reply with natural voices. Both integrate with agent SDKs so developers can build agents that listen, understand, and speak.
## Architecture overview
A modular pipeline lets you swap components depending on latency and quality requirements. Typical pipeline steps:
1. Capture audio (microphone stream or uploaded file)
2. Transcribe audio to text (WhisperInput)
3. Detect source language (Whisper metadata or an LLM)
4. Translate using an LLM or an external translation API
5. Output translated text and/or synthesize speech with TTS
This pipeline supports synchronous (real-time streaming) and asynchronous (batch) workflows — choose based on latency and accuracy needs.
## WhisperInput (speech-to-text)
WhisperInput is the transcription tool in the agent SDK. It supports:
* File mode — submit a complete audio file (`.mp3`, `.wav`, `.m4a`) for full transcription and richer post-processing.
* Streaming mode — send audio chunks progressively for low-latency partial transcripts.
Streaming is essential for live translation, meeting captioning, and interactive voice agents. WhisperInput can emit partial transcripts that enable incremental translation and faster perceived response times.
## Language detection and translation flow
Language detection can be inferred from Whisper’s metadata or by passing the transcription to an LLM for robust detection. After detecting the source language, translate using either:
* An LLM (e.g., GPT-family) for context-aware translation, or
* A specialized translation API (e.g., DeepL) when domain-specific or high-fidelity translations are required — see DeepL for specialized translation capabilities: [https://www.deepl.com/translator](https://www.deepl.com/translator)
For context-sensitive translations (tone, formality, intent), include:
* Conversation context
* Speaker metadata (role, formality preference)
* Domain or glossary constraints
These inputs help preserve style, register, and speaker intent — critical for healthcare, support, and legal contexts.
## Output options (text and TTS)
Translated results can be delivered as:
* Plain text or downloadable caption files (SRT, VTT)
* Synthesized speech (TTS API) for hands-free playback
* Streaming partial text + partial audio for live experiences
TTS options let you choose voice, language locale, and prosody to match user expectations and cultural norms.
## Streaming vs. batch processing
Choose the processing mode based on the application’s latency and accuracy demands.
| Mode | Use cases | Advantages | Considerations |
| --------- | ---------------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------------------- |
| Streaming | Live meetings, real-time interpreters | Low latency, partial transcripts and translations | Requires chunking, buffering, and state handling between segments |
| Batch | Podcast transcription, legal recordings, detailed analysis | Higher accuracy, allows post-processing, full context | Higher latency, needs full file upload |
Streaming is best for immediate feedback; batch is best for accuracy and deep analysis.
## Memory and context integration
Integrate memory to maintain context across a session and across interactions. Memory enables:
* Consistent speaker identity and personas
* Terminology and preferred translations (company terms, user nicknames)
* Persistent language preferences and formality level
Use in-memory session state for short-term continuity, and encrypted persistent storage for long-term personalization, with explicit user consent.
## Use cases
Speech translation agents are valuable across industries:
* Customer support: real-time interpretation for international callers
* Education: live translations in multilingual classrooms
* Travel: real-time travel assistants and kiosks
* Healthcare: telehealth interpreters and appointment support
* Meetings: live translation and multilingual meeting summarizers
* Language learning: tutors giving spoken feedback and translations
## Limitations and best practices
Key limitations and recommended mitigations:
* Audio quality: background noise, heavy accents, and low-fidelity recordings reduce accuracy. Use noise suppression and high-quality mics.
* Context preservation: include conversation and speaker metadata to preserve tone and intent.
* Fallbacks: design graceful fallback flows when speech is unintelligible (request repetition, provide transcripts, surface confidence scores).
* Latency: for real-time apps, prefer streaming with partial outputs and tuned chunk sizes.
* Data privacy: treat audio as sensitive data. Encrypt, limit retention, and obtain consent.
Always implement strong privacy protections for audio data. Obtain user consent before recording, use secure transmission and storage, and apply data retention policies to limit exposure.
## Example high-level flow (pseudo-code)
Below is a concise logical sequence for a speech translation agent. Replace pseudo calls with your SDK/API specifics and error handling.
```javascript theme={null}
// Capture audio (file or stream) into `audioBuffer`
// 1) Transcribe with WhisperInput (file or streaming)
const transcription = await agent.callTool("whisper_input", {
audio: audioBuffer, // or streaming chunks
format: "text"
});
// 2) Detect language (Whisper may return language metadata)
const detectedLanguage = transcription.language || await detectLanguage(transcription.text);
// 3) Translate the text (LLM or external API)
const translatedText = await translateText(transcription.text, {
from: detectedLanguage,
to: "en" // target language
});
// 4) Optionally synthesize speech with TTS
const speechAudio = await agent.callTool("tts_api", {
text: translatedText,
voice: "default",
language: "en-US"
});
// Return both text and audio output
return { text: translatedText, audio: speechAudio };
```
For real-time scenarios, process audio in small chunks and stream partial transcripts and translations to the client for lower perceived latency.
## Final recommendations
* Design modular pipelines: separate capture, transcription, detection, translation, and TTS so you can iterate on components independently.
* Profile streaming vs. batch in your environment to find optimal chunk sizes and latency/accuracy trade-offs.
* Surface confidence scores and human-in-the-loop review for safety-critical domains.
* Localize voice and translation settings to match user expectations for formality and dialect.
* Test widely: diverse accents, noisy environments, and target demographics to ensure robustness.
Speech translation agents, when designed with careful architecture, suitable audio tooling, and attention to privacy and user experience, enable accessible, culturally aware, and useful multilingual voice interactions.
# Demo Automatic Language Recognition and Translation
Source: https://notes.kodekloud.com/docs/AI-Agents/Advanced-Agents-Projects/Demo-Automatic-Language-Recognition-and-Translation/page
Asynchronous Python pipeline that transcribes WAV audio, detects language and emotion, translates to English, and generates concise summaries and suggested titles using OpenAI models.
Welcome back.
In this lesson we'll build an asynchronous audio-to-insight pipeline that:
* Accepts a WAV audio file
* Transcribes the audio
* Detects the spoken language and a prevailing emotion/tone
* Translates the transcription into English
* Generates a concise summary and a suggested title
This design separates each step into small, composable async functions so you can reuse or replace individual components (for example swapping models or custom agents).
Store your [OpenAI API key](https://platform.openai.com/account/api-keys) in a `.env` file (for example `OPENAI_API_KEY=`). This lesson will load environment variables via [python-dotenv](https://pypi.org/project/python-dotenv/).
Quick overview — Pipeline steps and the corresponding functions:
| Step | Purpose | Function |
| ---- | ------------------------------------------- | ------------------------------ |
| 1 | Transcribe WAV audio to text | `transcribe_audio` |
| 2 | Detect language and one-word emotional tone | `analyze_language_and_emotion` |
| 3 | Translate text to English | `translate_text` |
| 4 | Produce suggested title and short summary | `generate_title_and_summary` |
## Setup and imports
Load environment variables, initialize the OpenAI client, and import utilities. This example uses the modern [OpenAI Python client](https://github.com/openai/openai-python) (`OpenAI()`), plus an assumed `agents` package providing `Agent` and `Runner` as used in the original material.
```python theme={null}
from dotenv import load_dotenv
import os
from pathlib import Path
import asyncio
import re
# OpenAI Python client
from openai import OpenAI
# Optional display in notebooks
from IPython.display import Image, display
# Agent & Runner (kept as in the original content)
from agents import Agent, Runner
# Load environment variables
load_dotenv()
# Initialize OpenAI client
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
```
Be mindful of API usage and costs when using large models like `gpt-4` and uploading audio files. Use lower-cost models for development and testing if desired.
## Transcription (Whisper)
We create an async helper to upload a WAV file to the Whisper transcription model and return the transcription text. The function validates the path and handles common return shapes from the client.
```python theme={null}
async def transcribe_audio(file_path: str) -> str:
"""
Transcribe a WAV file using the Whisper model and return the transcription text.
"""
# Ensure the file exists
path = Path(file_path)
if not path.exists():
raise FileNotFoundError(f"Audio file not found: {file_path}")
with open(file_path, "rb") as audio_file:
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=audio_file
)
# The client returns an object with a text attribute for the transcript
return getattr(transcript, "text", transcript.get("text") if isinstance(transcript, dict) else None)
```
Reference: Whisper docs — [https://platform.openai.com/docs/models/whisper-1](https://platform.openai.com/docs/models/whisper-1)
## Language and Emotion Analysis
Use a chat model to detect the language and provide a one-word emotional descriptor. The function uses a deterministic temperature (0.3) and extracts values using tolerant regular expressions to handle slightly varied replies.
```python theme={null}
async def analyze_language_and_emotion(text: str) -> dict:
"""
Ask a chat model to detect the language and a one-word emotional tone for the given text.
Returns: {"language": "", "emotion": ""}
"""
system_msg = (
"You're an AI that analyzes messages. Detect the language (e.g., English, French) "
"and describe the emotional tone in one word (e.g., joyful, sad, angry, professional, excited, persuasive). "
"Respond in the format:\nLanguage: \nEmotion: "
)
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": system_msg},
{"role": "user", "content": f"Here is the message:\n{text}"}
],
temperature=0.3
)
content = response.choices[0].message.content.strip()
# Tolerant regex to capture "Language: ..." and "Emotion: ..." (allow multi-word and punctuation)
language_match = re.search(r"(?i)^\s*Language[:\-\s]*([^\r\n]+)", content, re.MULTILINE)
emotion_match = re.search(r"(?i)^\s*Emotion[:\-\s]*([^\r\n]+)", content, re.MULTILINE)
return {
"language": language_match.group(1).strip() if language_match else "Unknown",
"emotion": emotion_match.group(1).strip() if emotion_match else "Unknown"
}
```
Note: temperature is set to 0.3 to favor more deterministic outputs, which helps reliable parsing of the model response.
## Translator Agent and translate\_text
This example uses a simple Agent to translate text into English and a Runner to execute it. The Agent/Runner implementation is assumed from the original content; if your agents package returns different shapes, adapt the result extraction accordingly.
```python theme={null}
translator_agent = Agent(
name="Translator",
instructions="Translate the input text into English. Only return the translated result."
)
async def translate_text(text: str) -> str:
"""
Use the Agent Runner to translate text into English.
Returns the final translated string returned by the agent.
"""
result = await Runner.run(translator_agent, input=text)
# Handle common return shapes: string, object with attribute, or dict
if isinstance(result, str):
return result
return getattr(result, "final_output", result.get("final_output") if isinstance(result, dict) else None)
```
If your agents/runner implementation differs, adapt the return extraction accordingly.
## Title and Summary Generation
Ask a chat model to provide a concise summary and a suggested title. Temperature is slightly higher for creativity (0.5).
```python theme={null}
async def generate_title_and_summary(text: str) -> str:
"""
Generate a concise summary and a suggested title for the given text.
Returns a string containing both title and summary.
"""
system_msg = "You are a helpful AI assistant. Summarize the user's message and suggest a title for it."
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": system_msg},
{"role": "user", "content": f"Here's the text:\n\n{text}"}
],
temperature=0.5
)
return response.choices[0].message.content.strip()
```
Tip: If you prefer structured outputs (e.g., JSON with `title` and `summary`), ask the model to respond in JSON and parse the result. For simple display, the free-text response above often suffices.
## Full pipeline: process\_audio\_translation
This orchestrator composes the previous functions into a complete asynchronous flow. Each step's output is printed; you can replace prints with logging, storage, or event emissions for production usage.
```python theme={null}
async def process_audio_translation(file_path: str):
"""
Full pipeline for an audio file:
1. Transcribe audio
2. Analyze language and emotion
3. Translate into English
4. Generate title and summary
Prints each result step to the console.
"""
# 1) Transcribe
transcript = await transcribe_audio(file_path)
print(f"Transcript:\n{transcript}\n")
# 2) Language & emotion analysis
analysis = await analyze_language_and_emotion(transcript)
print(f"Detected language: {analysis['language']}")
print(f"Detected emotion: {analysis['emotion']}\n")
# 3) Translate to English
translation = await translate_text(transcript)
print(f"Translation:\n{translation}\n")
# 4) Title & summary
extras = await generate_title_and_summary(translation)
print(f"Title and Summary:\n{extras}\n")
```
## Run the pipeline
Pass in the full path to your WAV file. In Jupyter or other async-capable REPLs you can `await` the function directly.
```python theme={null}
# Replace with the path to your WAV file
audio_path = "/Users/gavinridgeway/Documents/Anaconda/AiAgent/final_fixed.wav"
await process_audio_translation(audio_path)
```
If running from a standard Python script, wrap the call in asyncio:
```python theme={null}
if __name__ == "__main__":
audio_path = "/path/to/your/file.wav"
asyncio.run(process_audio_translation(audio_path))
```
## Troubleshooting common issues
* File not found: ensure the `file_path` is correct and accessible by your process.
* UnboundLocalError or NameError: double-check variable names and that you return the expected attributes (for example `result.final_output`).
* API key errors: confirm `OPENAI_API_KEY` is set and loaded via `load_dotenv()` or environment variables.
* Agent/Runner differences: the `agents` package usage (Agent, Runner) is retained from the original content — adapt `Runner.run()` and result access if your agents library returns different shapes.
* Unexpected model output format: prefer instructing the model to respond in a strict format (for example `Language: \nEmotion: ` or JSON), then validate with regex or a JSON parser.
## Example output (expected)
After running on a French sample, the pipeline prints something like:
* Transcript: "Apprendre à programmer, c'est comme avoir un super-pouvoir..."
* Detected language: French
* Detected emotion: Encouraging
* Translation: "Learning to program is like having a superpower..."
* Title and Summary: (a short summary and a suggested title)
You now have a working asynchronous pipeline that transcribes audio, detects language and emotion, translates into English, and generates a title plus a short summary.
## Links and References
* [OpenAI API docs](https://platform.openai.com/docs/)
* Whisper model: [https://platform.openai.com/docs/models/whisper-1](https://platform.openai.com/docs/models/whisper-1)
* GPT models: [https://platform.openai.com/docs/models](https://platform.openai.com/docs/models)
* [python-dotenv](https://pypi.org/project/python-dotenv/)
* Jupyter: [https://jupyter.org](https://jupyter.org)
If you want to extend this pipeline: consider adding speaker diarization, punctuation normalization, or persisting outputs to a database for downstream search and analytics.
# Demo Building a Multi Agent System
Source: https://notes.kodekloud.com/docs/AI-Agents/Advanced-Agents-Projects/Demo-Building-a-Multi-Agent-System/page
Guide to building a recruiter multi agent system that extracts job keywords, scans PDF resumes, transcribes interviews, analyzes alignment, and orchestrates tools into a consolidated report
Welcome back. In this lesson we’ll build a practical multi‑agent system that helps a recruiter automate screening and interview analysis.
What is a multi‑agent system?
A multi‑agent system is composed of multiple specialized agents (or tools), each with a narrow role. Agents coordinate by passing tasks or data downstream, while a coordinator (or orchestrator) agent controls the overall workflow and composes a final result.
Project overview
We’ll assemble a recruiter-focused system that does the following:
* Extract relevant skills and responsibilities from a job description.
* Scan local PDF resumes for matches to those skills.
* Transcribe an interview audio file and analyze whether the interview questions align with the job posting.
* Produce a consolidated report with extracted keywords, resume matches, and interview relevance feedback.
This guide contains the end-to-end implementation and an example runner to execute the workflow.
Ensure your environment variables are configured (for example via a `.env` file). Set your OpenAI API key at a minimum. Also update `RESUME_DIR` and `INTERVIEW_AUDIO_PATH` to match your local filesystem.
## Table: Tools and Responsibilities
| Tool name | Responsibility | Returns / Example |
| --------------------------------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `extract_keywords_from_job_description` | Extract 10–15 skills, tools, responsibilities from a job description | `["Python","React","REST APIs", ...]` |
| `scan_resumes_for_keywords` | Scan all PDF resumes in `RESUME_DIR` and return matches | `[{ "filename": "resume.pdf", "keyword": "Python", "match_snippet": "...", "page": 2 }]` |
| `transcribe_interview` | Transcribe interview audio using OpenAI speech-to-text | `"Full transcript text..."` |
| `analyze_interview_relevance` | Compare transcript to job description and return recommendations | `"Assessment: ... actionable suggestions ..." ` |
## Imports and configuration
Start by loading environment variables and importing required libraries. Adjust imports if your project uses different modules or versions.
```python theme={null}
from dotenv import load_dotenv
load_dotenv()
import os
import asyncio
import re
from pathlib import Path
from agents import Agent, Runner, ModelSettings
from agents.tool import function_tool
import fitz # PyMuPDF for reading PDFs
import openai
```
Set the resume directory and other paths (update to suit your environment):
```python theme={null}
RESUME_DIR = Path("/Users/gavinridgeway/Documents/Anaconda/AiAgent/Resume")
```
## Tool 1 — Scan resumes for keywords
This tool opens each PDF in `RESUME_DIR`, searches for each keyword (case-insensitive), and returns matches containing filename, keyword, surrounding snippet, and page number.
```python theme={null}
@function_tool(name_override="scan_resumes_for_keywords")
def scan_resumes_for_keywords(keywords: list[str]) -> list[dict]:
"""
Scan all PDF resumes in RESUME_DIR for keyword occurrences.
Returns a list of dicts:
[
{
"filename": "resume.pdf",
"keyword": "Python",
"match_snippet": "...context around the match...",
"page": 2
},
...
]
"""
results: list[dict] = []
for file in RESUME_DIR.glob("*.pdf"):
try:
doc = fitz.open(str(file))
except Exception as e:
# Skip files that can't be opened
continue
for page in doc:
text = page.get_text() or ""
for kw in keywords:
idx = text.lower().find(kw.lower())
if idx >= 0:
start = max(0, idx - 75)
snippet = text[start:start + 250].strip()
results.append({
"filename": file.name,
"keyword": kw,
"match_snippet": snippet,
"page": page.number + 1
})
doc.close()
return results
```
Best practices:
* Normalize keywords before searching to improve match quality.
* Consider using more advanced NLP (lemmatization, fuzzy matching) for improved recall.
## Tool 2 — Extract keywords from a job description
Use the LLM to extract 10–15 focused skills, tools, and responsibilities. Provide a clear system instruction and parse the model output into a clean list.
```python theme={null}
@function_tool(name_override="extract_keywords_from_job_description")
def extract_keywords_from_job_description(job_text: str) -> list[str]:
"""
Use the LLM to extract 10-15 key skills/tools/responsibilities from the job_text.
Returns a list of keywords.
"""
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[
{
"role": "system",
"content": "Extract 10–15 key skills, tools, and responsibilities from this job description."
},
{"role": "user", "content": job_text},
],
temperature=0.3
)
response_text = response["choices"][0]["message"]["content"]
lines = response_text.splitlines()
# Strip bullets, numbering, and any leading/trailing whitespace
keywords = [line.strip(" -•*0123456789.").strip() for line in lines if line.strip()]
return keywords
```
Tip: If the LLM returns multi-word phrases, keep them as-is (e.g., `REST APIs`, `containerization`) to preserve context for resume scanning.
## Tool 3 — Transcribe interview audio
Transcribe interviews using OpenAI’s speech-to-text model. This function returns the transcription text extracted from the audio file.
```python theme={null}
@function_tool(name_override="transcribe_interview")
def transcribe_interview(file_path: str) -> str:
"""
Transcribe an audio file (wav, mp3, etc.) using OpenAI's Whisper model.
Returns the transcript text.
"""
with open(file_path, "rb") as audio_file:
transcript = openai.Audio.transcribe(model="whisper-1", file=audio_file)
# The response includes a 'text' field
return transcript.get("text", "").strip()
```
Note: Transcription quality depends on audio clarity, sampling rate, and accents. Preprocessing (noise reduction, splitting long files) can improve results.
## Tool 4 — Analyze interview relevance
Compare the transcript against the job description and return a human-readable assessment that highlights areas that were strong, missing, or overemphasized, plus actionable suggestions.
```python theme={null}
@function_tool(name_override="analyze_interview_relevance")
def analyze_interview_relevance(interview_text: str, job_description: str) -> str:
"""
Using the LLM, evaluate how well the interview questions align with the job description.
Return a detailed, human-readable assessment.
"""
system_msg = (
"You are an HR assistant. Evaluate how well the interview questions align with the job description. "
"Be specific and helpful. Mention which areas were strong, which were missing, and provide actionable suggestions."
)
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[
{"role": "system", "content": system_msg},
{
"role": "user",
"content": f"Interview:\n\n{interview_text}\n\nJob Description:\n\n{job_description}"
}
],
temperature=0.4
)
return response["choices"][0]["message"]["content"].strip()
```
Suggestion: For more structured outputs, ask the LLM to return a JSON object with keys like `strengths`, `gaps`, and `recommendations`, then parse it programmatically.
## Coordinator agent — The AI Recruiter Assistant
Now compose the tools into a coordinator Agent that orchestrates the full workflow. The agent pulls together keyword extraction, resume scanning, transcription, and interview analysis, and returns a consolidated report.
```python theme={null}
recruiter_agent = Agent(
name="Ai Recruiter Assistant",
instructions="""
You are helping a recruiter. Workflow:
1) Extract keywords from the job description.
2) Scan local resumes for keyword matches.
3) Transcribe the interview audio file.
4) Analyze how well the interview questions align with the job description.
Return a single consolidated report containing:
- Extracted keywords
- Resume keyword matches (filename, keyword, snippet, page)
- Interview transcript summary and alignment feedback
Be concise but thorough; include actionable suggestions where appropriate.
""",
tools=[
extract_keywords_from_job_description,
scan_resumes_for_keywords,
transcribe_interview,
analyze_interview_relevance
],
model="gpt-4",
model_settings=ModelSettings(truncation="auto")
)
```
Design note: Keeping each `@function_tool` narrow and focused makes it easy to test, reuse, and replace components (for example, swapping Whisper for another transcription service).
## Running the system
Create the job description and set the interview audio path. Update paths and job text to match your use case.
```python theme={null}
JOB_DESCRIPTION = """
We're hiring a full-stack engineer with experience in React, Python, REST APIs, and deployment on cloud platforms like AWS or GCP.
The role involves building scalable services, collaborating with product and design, and occasionally supporting data engineering tasks.
Experience with containerization, CI/CD, and monitoring is a plus.
"""
INTERVIEW_AUDIO_PATH = "/Users/gavinridgeway/Documents/Anaconda/AiAgent/Resume/audio_interview.MP3"
prompt = f"""
Please process this job description:
{JOB_DESCRIPTION}
Then scan local resumes for matches using scan_resumes_for_keywords. Finally, transcribe the audio file at:
{INTERVIEW_AUDIO_PATH}
and analyze whether the interview questions align with the job description.
"""
```
The Runner interface is asynchronous. Use an async entrypoint to execute the agent and print the final report. Modify this to fit your runtime or Runner API if necessary.
```python theme={null}
async def main():
result = await Runner.run(recruiter_agent, input=prompt)
# The Runner returns a structured result — print the final output from the agent.
print(result.final_output)
if __name__ == "__main__":
asyncio.run(main())
```
## Example output (what to expect)
When executed, the agent should produce:
* A list of extracted keywords from the job description (10–15 items).
* Resume matches found in your PDF files, each with filename, keyword, snippet, and page number.
* A transcript of the interview audio.
* A detailed analysis explaining which interview questions aligned with the job description and which areas were under- or over-emphasized, including actionable suggestions.
Example scenario: The system might identify candidates matching “React” and “REST APIs” while noting the interview focused heavily on data-analysis topics (SQL, Excel), indicating a misalignment with the software engineering role.
## Recap & next steps
* Each `@function_tool` acts as a specialized sub-agent (resume scanning, keyword extraction, transcription, interview analysis).
* The `Agent` object composes these tools and orchestrates the full pipeline.
* Tools are modular and reusable—swap or extend them as needed.
Possible enhancements:
* Improve keyword extraction (synonyms, fuzzy matching, weighted scoring).
* Parse resumes into structured fields (name, email, experience years) for richer filtering.
* Add automated candidate ranking and prioritization.
* Request structured analysis output (JSON) from the LLM for programmatic post-processing.
## Links and references
* [OpenAI API keys](https://platform.openai.com/account/api-keys)
* [OpenAI Speech-to-Text guide](https://platform.openai.com/docs/guides/speech-to-text)
* [OpenAI Chat guide](https://platform.openai.com/docs/guides/chat)
* [PyMuPDF (fitz) documentation](https://pymupdf.readthedocs.io/)
* [dotenv (python-dotenv)](https://pypi.org/project/python-dotenv/)
Be mindful of API usage and costs. Transcribing long audio files and multiple LLM calls can incur charges—batch and rate-limit requests where possible. Also ensure you have consent and comply with relevant privacy requirements when processing candidate data.
# Understanding Multi Agent Systems
Source: https://notes.kodekloud.com/docs/AI-Agents/Advanced-Agents-Projects/Understanding-Multi-Agent-Systems/page
Overview of multi-agent systems covering architectures, agent roles, communication and coordination patterns, planning, observability, tools, applications, design challenges, and best practices
Welcome back.
In this lesson we introduce multi-agent systems (MAS): how they work, where they’re used, and practical design patterns for building robust, observable agent ecosystems.
We’ll cover:
* What MAS are and why they matter
* Key characteristics and emergent behavior
* Centralized vs decentralized architectures (pros/cons)
* Agent roles and responsibilities
* Communication and coordination models
* Common application and workflow patterns
* Planning, task allocation, and memory
* Tools, frameworks, and integration examples
* Design challenges, observability, and best practices
Multi-agent systems simulate environments where multiple autonomous entities (agents) cooperate, compete, or coordinate to solve complex tasks. MAS span many domains — from traffic management and robotics to research assistants and customer support automation. Understanding MAS fundamentals is essential for building scalable solutions that rely on collaboration, role negotiation, and real-time decision-making.
## Core concepts
At its core, a multi-agent system consists of multiple agents that operate autonomously — each with its own goals, decision logic, and (often) private state. Typical agent capabilities include:
* Communicating, negotiating, and coordinating with peers
* Working independently or collaboratively on subtasks
* Calling external tools and services (search APIs, databases, LLMs, solvers)
MAS are especially well-suited to distributed environments where no single agent can efficiently cover every responsibility. They mirror human teams: individuals with specialized roles working toward shared or intersecting objectives.
This diagram shows a human-in-the-loop MAS with a central orchestration module that manages task routing among specialist agents. A human operator supplies high-level prompts and constraints; the orchestrator routes tasks to agents such as an LLM reasoner, web-search tool, or document generator. Agents remain modular and can act independently or collaboratively while following orchestration logic.
The feedback loop between human, orchestrator, and agents enables real-time refinement and keeps the system responsive across workflows.
## Distribution, homogeneity, and communication
Multi-agent systems are typically distributed — there is no single inherent point of control unless you introduce a centralized orchestrator. Agents can be:
* Homogeneous: identical architecture and function
* Heterogeneous: different capabilities, specializations, or trust levels
Communication is a hallmark of MAS. Agents exchange messages to share state, assign work, or broadcast decisions. Interaction patterns range from fully cooperative to competitive (e.g., bidding or market-based allocation).
Emergent behavior is another crucial concept: system-level outcomes that arise from many local interactions and that were not explicitly programmed into any single agent. Emergence can produce useful, novel solutions — but it can also cause unexpected, undesirable behaviors. Plan for observation, logging, and safety constraints.
## Common application patterns
Typical MAS patterns let teams of agents specialize and compose capabilities to solve complex tasks:
* Solver workflows: Agents with analysis or numerical solver skills collaborate to process inputs, run solvers, and validate results.
* Coding workflows: A planner decomposes tasks and assigns CodeWriter and Reviewer agents; a safety guard verifies results.
* Conversational workflows: Multiple agents manage multi-party dialogues for AI tutors or advanced chat assistants.
* Business automation: Agents interact with APIs, databases, and spreadsheets to automate processes (invoicing, onboarding).
* Online decision-making: Agents perform web searches, aggregate API results, and return recommendations.
* Retrieval-augmented generation (RAG): Agents query knowledge bases and incorporate retrieved evidence into generated outputs.
* Custom domain flows: Specialized agents access centralized tool layers to interact with external systems.
For quick comparison, here’s a compact view of orchestration styles:
| Architecture | Description | Pros | Cons |
| ------------- | --------------------------------------------------------- | ----------------------------------------- | --------------------------------------------- |
| Centralized | Single orchestrator assigns tasks and sequences execution | Simpler coordination, global optimization | Single point of failure, potential bottleneck |
| Decentralized | Agents make local decisions and coordinate via protocols | Resilient, scalable, fault-tolerant | Harder to ensure consistency and debug |
In practice, most systems combine central planners (meta-agents) with specialist worker agents.
## Agent roles and coordination mechanisms
Agent roles typically fall into two buckets:
* Specialist agents: Narrow, repeatable functions (parsing, summarizing, classification). Efficient and reliable within a scoped domain.
* Generalist agents / planners: Higher-level reasoning and decomposition. They assign subtasks, restructure plans, and handle exceptions.
Coordination mechanisms include:
| Mechanism | Typical transport or pattern | Suitable for |
| ----------------------------- | ------------------------------------- | ----------------------------------------- |
| Direct messaging | JSON/HTTP, gRPC, websockets | Low-latency exchanges and RPC-style calls |
| Shared memory / blackboard | Distributed datastore or memory store | State sharing and indirect coordination |
| Pub/Sub | Kafka, Redis pub/sub, message brokers | Event-driven interactions and broadcast |
| Negotiation / contract-net | Bidding, auctions | Task allocation with competition |
| Token-passing / master-worker | Leader election, sequential control | Ordered workflows and resource sharing |
Choose coordination based on latency, consistency needs, and trust assumptions. Clear protocols avoid task overlap, conflicting actions, and resource contention.
## Design challenges and observability
MAS introduce unique challenges:
* Communication delays and message ordering issues
* Inconsistent state across distributed agents
* Unclear ownership of tasks and responsibilities
* Redundant computation and wasted cycles
* Conflict resolution complexity and race conditions
* Scaling and observability concerns
Best practices to mitigate these risks:
* Define clear, well-scoped agent roles and interfaces
* Favor modularity so agents are developed and tested independently
* Implement comprehensive logging of messages, plans, and tool calls
* Use capability schemas or contracts to align expectations between agents
* Limit agent scope to reduce state conflicts and simplify reasoning
* Standardize prompt templates and memory formats across agents
* Stage testing in simulated environments to expose coordination issues before production
Designers must plan for fault tolerance: fallback behaviors, retries, timeouts, and rich tracing make MAS safer and easier to debug.
## Planning, task allocation, and memory
A common decomposition pattern:
1. Planner agent breaks a high-level goal into subtasks.
2. Subtasks are routed to worker agents — either by the planner or via a bidding/negotiation process.
3. Worker agents execute tasks, call external tools, and return results.
4. Planner aggregates, validates, and finalizes outputs.
Combining planning with persistent agent memory enables learning from past decisions and reusing successful workflows, improving efficiency and accuracy over time.
## Tools, frameworks, and ecosystems
Modern frameworks simplify MAS design and orchestration:
Key projects and ecosystems:
* AutoGen — orchestrate role-based agent workflows and OpenAI model integrations: [https://github.com/microsoft/autogen](https://github.com/microsoft/autogen)
* LangGraph — graph-based programming model for agent flows, memory, and tool use: [https://learn.kodekloud.com/user/courses/langgraph](https://learn.kodekloud.com/user/courses/langgraph)
* CrewAI and role-assignment interfaces — delegate work across agent roles
* OpenAI SDKs, Hugging Face agent kits, and custom orchestration libraries provide messaging and tools primitives
Other resources:
* [OpenAI Platform docs](https://platform.openai.com/docs)
* [Hugging Face documentation and agent toolkits](https://huggingface.co/docs)
## Example research pipeline (pattern)
A typical multi-agent research pipeline:
* User requests a summary of the state of AI research.
* Planner decomposes the request into subgoals (scope, time range, topics).
* Research agent scrapes scholarly sources and extracts citations.
* Summarizer condenses findings; Writer produces a coherent narrative.
* Parallel execution accelerates throughput, while memory tracks sources and biases.
This pattern highlights how parallelism, memory, and role specialization improve outcome quality and traceability.
## MAS best practices checklist
* Define clear interfaces and capability contracts between agents
* Modularize agents for independent development and testing
* Log messages, tool calls, and state transitions for observability
* Limit scope per agent to simplify reasoning and reduce conflicts
* Use versioned prompt templates and shared memory schemas
* Simulate interactions and failure modes before production rollout
* Bake in retry logic, graceful degradation, and circuit breakers
When designing MAS, invest early in observability: traceable messages, centralized or distributed tracing, and reproducible test scenarios make debugging and safe deployment far easier.
Well-designed multi-agent systems balance specialization and generalization, select appropriate coordination protocols, and bake in observability and fault tolerance. When done right, MAS enable scalable, robust solutions that mirror collaborative human teams while leveraging automation and parallelism.
# Agentic Architecture and Inter Agent Communication
Source: https://notes.kodekloud.com/docs/AI-Agents/Agent-Architecture-Multi-Agent-Systems/Agentic-Architecture-and-Inter-Agent-Communication/page
Designing modular agent architectures, inter-agent communication patterns, and deploying scalable multi-agent systems with FastAPI, messaging, memory, and observability
In this lesson we examine agentic architecture and inter-agent communication—core concepts for building flexible, maintainable, and scalable multi-agent systems. We cover agent system layers, modular components, decoupled design benefits, common communication protocols and patterns, practical multi-agent workflows, and how to expose agents with FastAPI for production deployments.
Choosing the right architecture determines how well agents support long-horizon reasoning, persistent memory, tool orchestration, and autonomous operation. Decoupled designs enable independent upgrades, easier debugging, team-based development, and robust scaling. Clear inter-agent protocols let agents delegate, collaborate, and compose complex behaviors across services and runtime environments.
Agentic architecture refers to system designs that let AI agents operate as autonomous, extensible components. Typical subsystems include perception, planning, memory, action, and feedback mechanisms. These subsystems are integrated through modular services to form continuous reasoning loops.
## Four core layers of agentic systems
Four key layers commonly found in Agentic AI systems are described below. Each layer is responsible for discrete concerns, which simplifies testing and targeted scaling.
| Layer | Purpose | Examples / Tools |
| ------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| Perception Layer | Converts raw signals into structured observations from text, speech, or vision inputs | NLP pipelines, speech-to-text, OpenCV, ingestion pipelines |
| Cognitive Layer | Runs models and decision-making frameworks to reason, plan, and generate intents | LLMs, rule engines, planners, chain-of-thought modules |
| Action Layer | Executes effects: tool calls, API interactions, actuators, and feedback integration | API clients, webhooks, SDKs, robotics controllers |
| Communication Layer | Manages interactions across agents, services, and humans via well-defined protocols | REST, WebSockets, pub/sub systems, vector stores |
These layers let agents perceive, reason, act, and communicate in dynamic environments while keeping responsibilities separated.
## Modular components of an agent runtime
A practical agent system is composed of modular components with clear responsibilities:
* Controller / Planner: decomposes high-level goals into actionable tasks and routes work to agents or tools.
* Tool Executor: manages external API integrations, sandboxed function calls, and runtime tools.
* Memory System: stores and retrieves context and long-term state; often uses vector stores for embeddings and semantic search.
* Interface Layer: exposes agent capabilities to users or other systems via APIs, WebSockets, or SDKs.
* Agent Runtime Orchestrator: coordinates planning, tool invocations, retries, and response synthesis.
Separation of concerns like this improves testability, reuse, and independent scaling. For example, you can upgrade the planner model without modifying memory access or the interface layer.
## Inter-agent communication methods
Inter-agent communication enables delegation, knowledge sharing, and collaboration. Choose mechanisms based on latency, reliability, and coupling goals:
| Mechanism | Characteristics | Use cases |
| ------------------------ | ----------------------------------------------------------------- | --------------------------------------------------------- |
| REST APIs | Synchronous HTTP calls; simple, direct | Point-to-point requests, short-lived calls |
| Message queues / Pub‑Sub | Asynchronous, durable, decoupled (Redis Streams, RabbitMQ, Kafka) | Task orchestration, retries, fan-out, resilient workflows |
| Shared stores | Shared database or vector store for collaborative state | Shared context, caching, persistent memory across agents |
### Communication patterns
Common patterns for composing agent interactions:
* Request–Response: Agent A asks Agent B to perform work and waits for a result.
* Publish–Subscribe: Agents publish events or tasks; multiple subscribers react or process work.
* Supervisor–Worker: A coordinating agent delegates tasks to worker agents and aggregates results.
These patterns support collaboration, specialization, fault tolerance, and scalable execution.
Choose communication patterns based on latency, reliability, and coupling requirements. Use REST for simple synchronous calls, message queues for decoupled and resilient workflows, and shared stores for collaborative memory and caching.
## Conversable and collaborative agent capabilities
Key capabilities that enable agents to work together and interact with users:
* Agent customization: personalize agents with domain-specific tools, personas, plugins, or scripts.
* Multi-agent conversations: agents exchange messages for joint reasoning, handoffs, or validation.
* Flexible conversation patterns: support joint chat (a shared channel where all agents contribute) and hierarchical chat (a lead agent delegates to sub-agents).
## Practical multi-agent workflows
Common real-world workflows for multi-agent systems:
* Role-based teams: specialized agents (researcher, writer, fact-checker) collaborate to complete complex tasks.
* Escalation flows: when an agent cannot proceed, it calls a helper or supervisor agent.
* Negotiation: agents propose and score options, exchanging proposals until consensus.
* Pipeline chaining: one agent handles preprocessing and passes results to downstream agents (summarizer → verifier → publisher).
Agent collaboration models human team dynamics but requires well-defined messaging protocols, observability, and fault handling.
## FastAPI for exposing agent capabilities
[FastAPI](https://learn.kodekloud.com/user/courses/python-api-development-with-fastapi) is a modern, high-performance Python framework ideal for exposing agent capabilities. Reasons to use FastAPI:
* Asynchronous endpoints to integrate with async LLM calls and background tasks.
* Automatic OpenAPI / Swagger documentation generation.
* Strong input validation with [Pydantic](https://docs.pydantic.dev/).
* Easy dependency injection for authentication, policy checks, and observability.
A typical access-control workflow in a containerized environment follows these steps:
1. Client (user, web app, or another agent) sends a request to the FastAPI service.
2. FastAPI validates the request body with Pydantic models.
3. The application queries an external policy engine (HTTP or SDK) with inputs such as principal, action, and resource.
4. The policy engine returns allow/deny decisions; the application enforces the decision.
5. The decision and relevant metadata are logged for auditing.
This flow commonly runs inside a Docker container to ensure consistent runtime and dependency management.
### Example FastAPI endpoint (agent interface)
Below is a minimal FastAPI example demonstrating a Pydantic request model, async handler, and a placeholder policy check. Use this pattern to validate inputs and gate agent execution behind policy decisions.
```python theme={null}
from fastapi import FastAPI, Depends, HTTPException
from pydantic import BaseModel
from typing import Dict
app = FastAPI()
class AgentRequest(BaseModel):
user_id: str
prompt: str
metadata: Dict[str, str] = {}
async def check_policy(user_id: str, action: str) -> bool:
# Replace with a real policy engine call or SDK
# e.g., policy_client.evaluate({"principal": user_id, "action": action})
return True
@app.post("/agent/run")
async def run_agent(req: AgentRequest):
allowed = await check_policy(req.user_id, "run_agent")
if not allowed:
raise HTTPException(status_code=403, detail="policy denied")
# Invoke planner, memory lookup, and tool executor here (async)
result = {"status": "ok", "output": "agent result goes here"}
return result
```
### How FastAPI fits into agent architectures
Typical integration points and deployment patterns:
* Client sends requests: frontends or other agents call REST endpoints.
* FastAPI endpoints receive validated payloads via Pydantic schemas.
* Agent logic executes: planners, memory lookups, tool executors, and LLM calls run—often asynchronously or via background tasks.
* Response returned: structured JSON responses; auto-generated docs help developer onboarding.
FastAPI integrates well with microservice patterns—each agent role (planner, memory store, tool executor) can be containerized and scaled independently.
## Deployment and scaling strategies
Common deployment and scaling approaches for agent systems:
* Horizontal scaling: multiple worker instances behind a load balancer for stateless agents.
* Service separation: isolate planner, memory, and tool executors into separate services for targeted scaling.
* Async task queues: use Celery, RQ, or cloud-native job queues for long-running or retryable tasks.
* Observability: structured logging, distributed tracing, and metrics for debugging and performance tuning.
* Security and policy enforcement: centralize access control policies, use mTLS, API gateways, and rate limiting.
These patterns help create production-grade, maintainable, and observable agent deployments.
Security and observability are critical. Enforce least-privilege access, validate inputs thoroughly, log decisions for audits, and instrument distributed traces to troubleshoot inter-agent workflows.
## Quick reference: communication selection guide
| Goal | Recommended approach |
| ----------------------------- | -------------------------------------------------------- |
| Low-latency sync call | REST / gRPC |
| Decoupled, resilient pipeline | Message queue / Pub‑Sub (Kafka, RabbitMQ, Redis Streams) |
| Shared context or memory | Shared database / vector store |
| Fan-out to many workers | Pub‑Sub with consumer groups |
## Links and references
* [FastAPI docs and tutorials](https://learn.kodekloud.com/user/courses/python-api-development-with-fastapi)
* [Pydantic documentation](https://docs.pydantic.dev/)
* [Redis Streams](https://redis.io/docs/latest/streams/)
* [RabbitMQ](https://www.rabbitmq.com/)
* [Kafka event streaming course](https://learn.kodekloud.com/user/courses/event-streaming-with-kafka)
* [Kubernetes basics](https://learn.kodekloud.com/user/courses/kubernetes-for-the-absolute-beginners-hands-on-tutorial)
* [Docker primer](https://learn.kodekloud.com/user/courses/docker-training-course-for-the-absolute-beginner)
Together, these architectural principles, communication patterns, and deployment practices enable scalable, adaptable multi-agent systems able to solve complex, multi-step tasks in production environments.
# Autonomous Agent Frameworks
Source: https://notes.kodekloud.com/docs/AI-Agents/Agent-Architecture-Multi-Agent-Systems/Autonomous-Agent-Frameworks/page
Overview of autonomous agent frameworks, their architecture, core capabilities, example tools, selection guidance, and production best practices for safe, observable, and scalable autonomous AI systems.
Welcome back!
This lesson explains Autonomous Agent Frameworks: what they are, how they work, and how to choose and operate them safely in production.
Topics covered:
* Core capabilities of autonomous agents
* Key differences — autonomous vs. scripted agents
* The agent loop — Sense → Plan → Act → Reflect
* Example frameworks: Auto-GPT, AgentOps, SuperAGI, AutoGen
* Framework selection guidance and best practices for safe autonomy
Autonomous agent frameworks are the next evolution in AI systems. They enable agents to accept goals, plan multi-step strategies, invoke tools and APIs, persist state across sessions, and learn from outcomes with minimal human direction. Properly designed frameworks let agents handle open-ended tasks, recover from failures, and adapt to changing data and environments.
Autonomous agents extend single-prompt systems in several important ways:
* Persistence: Maintain state and memory across steps and sessions.
* Goal orientation: Decompose high-level objectives into subtasks and milestones.
* Tool orchestration: Discover, select, and chain external tools or APIs.
* Reflection: Evaluate outcomes and adjust future plans.
These behaviors rely on modular components such as planners, memory stores, tool layers, and execution pipelines. The diagram below shows a common agentic architecture where specialized agents collaborate to handle tasks end-to-end.
Typical flow in a modular autonomous system:
1. Input / Events: User requests or external triggers arrive via UI or API.
2. Observer agent: Performs initial analysis and converts events into contextualized tasks.
3. Task queue: Tasks are enqueued for processing.
4. Prioritizer: Reorders, deduplicates, or discards low-value tasks.
5. Execution agent: Pulls prioritized tasks, fetches relevant memory/context, chooses tools, and carries out actions.
6. Memory updates and responses: Results are stored and returned to users or external systems; memory updates inform future cycles.
Next, consider the functional building blocks that enable an agent to behave autonomously.
Core components (stack overview)
| Layer | Purpose | Examples / Notes |
| ------------------------- | ------------------------------------------------- | ----------------------------------------------------- |
| Users / APIs | Sources of goals and data that drive agents | UI, webhooks, scheduled jobs, integrations |
| Agent core | Persona, prompting strategy, planning rules | Prompt recipe / policy, constraints, planner |
| Memory & context | Short-term chat context and long-term storage | Embeddings, vector stores, RDBMS, caches |
| Tools layer | Access to enterprise assets and external services | Databases, cloud APIs, web crawlers, custom functions |
| Execution & orchestration | Task queues, prioritizers, worker agents | Job schedulers, orchestrators, retry policies |
These components enable agents to plan, act, and respond in real time while maintaining context and leveraging external systems.
Core autonomous capabilities
Autonomous systems require several capabilities to operate without constant human intervention:
* Goal decomposition & planning: Break goals into actionable subtasks and schedule them.
* Memory management: Maintain short-term context and long-term knowledge for decision making.
* Tool orchestration: Select, invoke, and compose tools to complete actions.
* Self-evaluation & feedback loops: Assess outcomes, log signals, and update strategies.
Comparison: Scripted vs Autonomous agents
Autonomous agents differ fundamentally from scripted systems in how they receive input, plan, use tools, and learn:
Key differences:
* Input handling:
* Scripted: Waits for direct user prompts; follows predefined flows.
* Autonomous: Can define goals and act proactively based on observations.
* Planning:
* Scripted: Rigid, hand-coded flows.
* Autonomous: Dynamic, adaptive planning that can re-plan with new information.
* Tool usage:
* Scripted: Calls a fixed set of functions.
* Autonomous: Selects and composes tools from a library as needed.
* Feedback:
* Scripted: Limited learning from past interactions.
* Autonomous: Incorporates signals to improve behavior over time.
Agent loop (Sense → Plan → Act → Reflect)
The agent loop is the core operational cycle that powers incremental progress and continuous improvement.
* Sense: Collect observations from inputs, system state, or memory — parse prompts, read files, query databases, or monitor services.
* Plan: Decompose objectives into subtasks, choose tools, and order actions or API calls.
* Act: Execute the plan — call tools/APIs, write files, or trigger other agents.
* Reflect: Evaluate outcomes, log metrics, update memory, and adjust future planning. Re-enter the loop with a revised plan when needed.
This cycle supports error correction, convergence to goals, and safe interference detection.
Auto-GPT and task-based loops
[Auto-GPT](https://github.com/Significant-Gravitas/Auto-GPT) is one of the earliest widely used open-source autonomous agent prototypes. It demonstrates a loop of prompting, task creation, memory storage, and tool use to complete multi-step objectives (for example, “build a website”). Auto-GPT is useful for prototyping but can face challenges with long-term context retention, robust error recovery, and enterprise-grade observability.
Flow example:
* User submits an objective.
* Execution agent performs tasks and writes results to memory.
* Task-creation agent uses memory to generate follow-up tasks.
* Prioritizer refines and orders the task queue for subsequent execution.
AgentOps: observability and lifecycle management
AgentOps is a meta-framework that adds production features—observability, governance, and lifecycle tooling—to agent deployments. It often integrates with frameworks like [LangChain](https://learn.kodekloud.com/user/courses/langchain) and [Auto-GPT](https://github.com/Significant-Gravitas/Auto-GPT) to capture logs, trace tool calls, visualize decision paths, and audit behavior. Observability and governance are critical for safe agent adoption in enterprises.
AgentOps commonly includes:
* CI/CD pipelines and deployment tooling for agents and tools
* Tool and agent registries
* Agent monitoring, metrics, and centralized logging
* LLM gateways and environment separation (dev/UAT/prod)
SuperAGI: production-grade orchestration and observability
[SuperAGI](https://github.com/superagi-dev/SuperAGI) targets production use cases with task queues, a GUI dashboard, multi-model support, and multiple memory backends. It supports parallel agent execution and visual tracing of tasks, aiding debugging and scaling. SuperAGI is extensible for custom tool integrations and operational telemetry.
A common hierarchical, multi-agent orchestration pattern—used by SuperAGI-style systems—has a central orchestrator delegating to specialized agents; sub-agents collaborate and aggregated results are returned with telemetry and retries handled at scale.
AutoGen: conversational multi-agent orchestration
[AutoGen](https://github.com/microsoft/autogen) (Microsoft) uses conversational interfaces between agents (and between users and agents) to coordinate task execution. Agents can ask clarifying questions, pass structured data, and collaborate via chat-style interactions. AutoGen supports memory modules, custom tools, and multi-step planning, making it well-suited for enterprise scenarios requiring formal coordination across teams and data sources.
Framework selection guidance
Choose frameworks based on your use case, maturity requirements, and operational constraints.
| Framework | Best for | Strengths |
| --------- | ------------------------------------ | --------------------------------------------------------- |
| Auto-GPT | Prototyping and personal experiments | Simple loop-based autonomy; fast to iterate |
| SuperAGI | Production-grade agents | Dashboards, job queues, telemetry, scale |
| AgentOps | Observability & governance | Auditing, lifecycle management, compliance |
| AutoGen | Conversational multi-agent workflows | Formal agent-to-agent coordination and tool orchestration |
Best practices and safeguards
* Control costs: Track and limit token usage and external tool calls.
* Resilience: Implement retry logic with exponential backoff and sensible timeouts.
* Guardrails: Enforce maximum step counts, budget limits, and runtime caps to avoid runaway processes.
* Least privilege: Grant minimal permissions for tool access and separate environments (dev/UAT/prod).
* Observability: Log every plan, tool invocation, memory access, and outcome for debugging and audits.
* Recovery: Add success/failure signals, automated rollback, and human-in-the-loop approvals for high-risk operations.
Autonomous agents can take irreversible actions if misconfigured. Always test agents in isolated environments, enable strict access controls, and add human-in-the-loop approval for high-risk operations.
Design considerations (quick checklist)
* Define clear goal boundaries and escalation paths.
* Instrument telemetry at the tool and plan levels.
* Use modular prompt recipes and policy constraints to control agent behavior.
* Validate memory sources and retention policies to avoid stale or biased context.
With a modular architecture, robust memory and tool integration, the Sense-Plan-Act-Reflect loop, and production-grade observability, you can build autonomous agents that are safe, auditable, and effective for real-world automation.
Links and references
* [Auto-GPT](https://github.com/Significant-Gravitas/Auto-GPT) — open-source autonomous agent prototype
* [SuperAGI](https://github.com/superagi-dev/SuperAGI) — production orchestration for agents
* [AutoGen (Microsoft)](https://github.com/microsoft/autogen) — conversational multi-agent framework
* [LangChain](https://learn.kodekloud.com/user/courses/langchain) — agent and chain tooling
For further reading:
* [Kubernetes Basics](https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/)
* [Docker Hub](https://hub.docker.com/)
* [Terraform Registry](https://registry.terraform.io/)
# Multi Agent Frameworks and Architecture
Source: https://notes.kodekloud.com/docs/AI-Agents/Agent-Architecture-Multi-Agent-Systems/Multi-Agent-Frameworks-and-Architecture/page
Guide to multi-agent systems covering architectures, interaction patterns, frameworks, coordination strategies, benefits, challenges, use cases, and best practices for building scalable, modular, and observable agent ecosystems.
Welcome back.
In this lesson, we’ll explore multi-agent frameworks and architecture. You’ll learn what multi-agent systems (MAS) are, why they matter, typical interaction and communication patterns, leading tools, strategies for role assignment and team coordination, ideal use cases, and best practices for building scalable MAS.
Multi-agent frameworks are essential for handling complex, multi-step tasks by distributing responsibilities across a network of collaborating agents. This mirrors human teams—planners, specialists, and reviewers working together toward a shared objective. Understanding MAS architecture helps you design systems that are modular, scalable, and capable of dynamic role allocation.
Multi-agent frameworks enable agent ecosystems that coordinate, adapt, and solve real-world problems through intelligent collaboration.
## What is a multi-agent system (MAS)?
A multi-agent system (MAS) is a distributed network of autonomous agents that interact to accomplish tasks that are difficult or inefficient for a single agent. Each agent may have distinct goals, memory, tools, or reasoning models; agents communicate and coordinate to complete a mission.
Key characteristics:
* Autonomous actors with private state and capabilities.
* Distributed decision-making and parallel execution.
* Communication via messages, events, or shared stores.
* Role specialization (planners, executors, verifiers, tool handlers).
MAS models team dynamics—division of labor, parallel execution, and problem-solving from multiple perspectives. Common application areas include workflow automation, document analysis, research synthesis, and game AI ecosystems.
## Single-agent vs multi-agent
* Single-agent systems: one decision maker; actions executed sequentially; simpler to design and debug; best for constrained or linear tasks.
* Multi-agent systems: multiple interacting agents; distributed decision-making; parallel task execution; more flexible and scalable for dynamic, large-scale, or heterogeneous environments.
## Supervisory (Coordinator) Agent Architecture
A common MAS pattern uses a supervisory (or coordinator) agent. Typical workflow:
1. A user request arrives at the supervisor.
2. The supervisor decomposes the task and delegates subtasks to specialized agents.
3. Sub-agents run independently or collaboratively, query tools, or access data sources.
4. Agents return results to the supervisor.
5. The supervisor aggregates, reconciles, and composes a final response.
This hierarchical coordination resembles a project manager model where the supervisor monitors progress, resolves conflicts, and ensures a coherent final output.
Example pseudocode (supervisor-delegate loop):
```python theme={null}
# pseudocode
supervisor.receive(request)
tasks = supervisor.decompose(request)
for t in tasks:
agent = supervisor.select_agent(t)
agent.assign(t)
responses = collect_responses(tasks)
final = supervisor.aggregate(responses)
return final
```
## Key benefits of multi-agent systems
* Parallelism: execute tasks concurrently.
* Specialization: agents optimized for specific skills or tools.
* Robustness and fault tolerance: agents can fail without collapsing the whole system.
* Scalability: add agents with minimal reconfiguration.
* Improved problem solving: decomposition and parallel processing speed solutions.
* Flexibility: update or replace agents independently.
## Challenges and trade-offs
* Coordination overhead: communication and synchronization add complexity and CPU/network usage.
* Conflict resolution: inconsistent outputs or competing goals must be reconciled.
* Latency and cost: distributed operation can increase response time and infrastructure costs.
* Debugging and observability: tracing distributed state and interactions is harder.
Designing an effective MAS requires balancing autonomy (agent independence) against coordination (global objectives and consistency).
Distributed coordination increases operational complexity: invest early in logging, tracing, and fault-injection tests to avoid brittle deployments.
## Interaction patterns in MAS
Common organizational and interaction patterns:
| Pattern | Description | When to use |
| ------------------------------------- | ------------------------------------------------------------- | --------------------------------------------------- |
| Leader-Follower (supervisor-delegate) | Central coordinator delegates tasks and aggregates results | When global consistency is required |
| Peer-to-Peer (decentralized) | Agents negotiate and collaborate without a central controller | Highly resilient systems or federated architectures |
| Market-based / Auction | Tasks are bid on and allocated dynamically | Dynamic resource allocation and load balancing |
| Blackboard | Shared workspace where agents post intermediate results | Complex pipelines with staged processing |
| Hierarchical | Multi-layer coordination with subteams | Large workflows with nested responsibilities |
## Communication mechanisms
Agents communicate using multiple primitives depending on latency, throughput, and coupling needs:
* Message passing: direct messages via queues or actor systems (synchronous or asynchronous).
* Publish/Subscribe: decouples producers and consumers with event brokers.
* Shared data store / blackboard: common repositories for state and intermediate artifacts.
* RPC/HTTP (REST, gRPC): integrate with external services and tools.
* Event streaming: high-throughput interactions using Kafka, Pulsar, or similar platforms.
Example message shape (JSON):
```json theme={null}
{
"msg_id": "1234",
"from": "agent_planner",
"to": "agent_worker_1",
"task": "extract_entities",
"payload": {
"document_id": "doc-0001",
"params": {"lang": "en"}
},
"timestamp": "2026-01-01T12:00:00Z"
}
```
For high-performance systems, choose streaming or actor-based models; for simpler integrations, REST/gRPC is often sufficient.
## Leading frameworks and tools
Choose a framework based on language, integration needs, deployment model, and communication primitives.
| Framework / Tool | Language / Focus | Notes & Links |
| ------------------------------ | ---------------- | ------------------------------------------------------------------------------------------------- |
| JADE | Java | Mature agent lifecycle + messaging: [https://jade.tilab.com/](https://jade.tilab.com/) |
| SPADE | Python | Lightweight agent platform for Python developers |
| Ray & Ray RLlib | Python | Scalable distributed compute + RL support: [https://www.ray.io/](https://www.ray.io/) |
| LangChain & orchestration libs | Python / JS | Useful for LLM-driven agents & tool routing: `https://learn.kodekloud.com/user/courses/langchain` |
| Kafka / Pulsar | Multi | Event streaming for high-throughput interactions |
## Role assignment & team coordination strategies
* Static assignment: roles fixed at design time — simple and predictable.
* Dynamic assignment: runtime allocation based on load, capability, or context.
* Auction/bidding: market-driven task allocation for flexible load distribution.
* Consensus protocols: required when agents must agree on shared state (e.g., replication).
* Supervisor-driven coordination: centralized assignment and reconciliation to enforce global constraints.
Choose strategies aligned with fault tolerance, latency, and consistency requirements.
## Where MAS shine (use cases)
* Complex workflows requiring multiple specialized skills (e.g., document processing pipelines).
* Research synthesis and knowledge aggregation from heterogeneous sources.
* Multi-step decision-making with modular tool access (e.g., LLM chains + external tools).
* Game AI and simulations with many autonomous actors.
* Distributed optimization and control systems.
## Best practices for building scalable MAS
* Define clear responsibilities and contract-driven agent interfaces.
* Keep agents loosely coupled and standardize messaging formats.
* Use robust communication middleware and service discovery.
* Implement centralized logging, metrics, and distributed tracing to ease debugging.
* Design graceful degradation and redundancy to handle failures.
* Start with simple coordination patterns and iterate toward more complexity.
* Automate tests with simulation environments and scenario-based testing.
When designing MAS, prioritize observability and contract-driven interfaces. These reduce debugging complexity and make it easier to evolve the system over time.
## Summary
Multi-agent architectures enable modular, scalable, and resilient systems by splitting complex tasks across specialized agents. While MAS introduce coordination and observability challenges, careful design—clear interfaces, appropriate communication patterns, and robust monitoring—lets MAS deliver significant gains in capability and scalability for real-world problems.
## Links and references
* [Kubernetes Documentation](https://kubernetes.io/docs/)
* [Event Streaming with Kafka](https://learn.kodekloud.com/user/courses/event-streaming-with-kafka)
* [LangChain course](https://learn.kodekloud.com/user/courses/langchain)
* Ray: [https://www.ray.io/](https://www.ray.io/)
* JADE: [https://jade.tilab.com/](https://jade.tilab.com/)
# Security and Ethical AI in Multi Agent Systems
Source: https://notes.kodekloud.com/docs/AI-Agents/Agent-Architecture-Multi-Agent-Systems/Security-and-Ethical-AI-in-Multi-Agent-Systems/page
Guidance on securing and ethically governing multi‑agent systems, covering threat surfaces, authentication, privacy, sandboxing, bias mitigation, and human oversight.
Welcome back!
This lesson covers security and ethical considerations for multi-agent systems (MAS). You’ll learn why security and ethics are critical in MAS, which threat surfaces are unique to multi-agent architectures (data leakage, collusion, adversarial agents), and practical controls such as identity/authentication, authorization, privacy handling, ethical alignment, bias mitigation, defensive architecture (sandboxing, limits, escalation), secure inter-agent communication, and human oversight. We close with an operational checklist for secure, ethical MAS deployments.
Multi-agent systems (MAS) raise both opportunity and risk. Multiple semi‑autonomous agents interacting across shared context, tools, and communication channels increase the complexity of safety, security, and governance. It’s not enough for each agent to be “smart” — the system as a whole must be designed to protect data, prevent misuse, and remain aligned with human values throughout interaction flows.
Why MAS expands the attack surface
Because agents can act independently and compose capabilities, risks multiply:
* More endpoints and credentials to secure.
* Greater chance of misinterpretation or conflicting objectives between agents.
* Shared memory and tooling increase blast radius for compromise.
* Harder to enforce consistent ethical rules and safety constraints across agents.
Key threat surfaces in MAS
Below are the most critical threat surfaces mapped to examples and mitigations to help you prioritize defenses.
| Threat surface | Example risk | Typical mitigations |
| --------------------------------------- | ---------------------------------------------------------------------------: | --------------------------------------------------------------------------------------------- |
| Communication spoofing and injection | An attacker sends a fake planner->writer message instructing harmful actions | Authenticate messages (mutual TLS / signed tokens), validate schema, reject unexpected fields |
| Shared memory poisoning | One agent writes false facts into shared context that other agents act on | Scoped memory views, write guards, content validation, versioned context with provenance |
| Tool and API abuse | Agent is tricked into calling payment or shell APIs via prompt injection | RBAC for tool access, sandboxed tool executions, approval gates for side‑effects |
| Emergent collusion / bias amplification | Agents repeatedly reinforce biased sources across a workflow | Source-tracking, diversity controls, bias audits, human review for high-risk outputs |
| Unauthorized escalation | Agent escalates privileges by chaining actions across agents | Least-privilege roles, enforce agent boundaries, strict authorization checks |
Design multi‑agent systems defensively
MAS failures can cascade across the system. Defensive design focuses on prevention, containment, and rapid detection:
* Create scoped memory (per-session or per-task isolation) and TTL for context.
* Sign and authenticate every message between agents.
* Apply least-privilege RBAC for tools, APIs, and data access.
* Run untrusted code in sandboxes and enforce runtime limits.
* Require layered verification or human approval for high-risk side effects.
* Maintain comprehensive, structured audit logs for observability and incident response.
Data leakage, collusion, and emergent behavior
When agents share memory or communicate with weak guards, sensitive data can leak or be persisted beyond intended scope. Agents may also collude (intentionally or accidentally) and amplify errors or bias through repeated reprocessing.
Defenses to consider:
* Strict session isolation and per-session encryption keys.
* Memory redaction, TTL (time-to-live) expiration, and automatic purging of ephemeral data.
* Behavioral monitoring and anomaly detection for agent outputs.
* Provenance tracking so downstream agents can weight or ignore low‑quality sources.
Identity, authentication, and authorization
Treat agent identity like microservice identity: verify who is speaking, restrict what they can do, and verify that actions are authorized.
Best practices:
* Issue per-agent credentials (API keys, tokens, service accounts).
* Use mutual TLS or signed tokens (for example, JWT) for inter-agent authentication. See Cloudflare’s guide to mutual TLS: [https://www.cloudflare.com/learning/ssl/what-is-mutual-tls/](https://www.cloudflare.com/learning/ssl/what-is-mutual-tls/) and JWT: [https://jwt.io/](https://jwt.io/).
* Apply role-based access control (RBAC) and least privilege: only grant the permissions required for an agent’s role.
* Enforce strict agent boundaries and monitor for privilege escalation patterns.
Handling sensitive information and privacy
Agents often handle PII and other confidential information. Apply standard data protection principles:
* Encrypt sensitive data in transit and at rest.
* Avoid persistent storage of sensitive context unless needed for compliance or audit.
* Implement memory redaction, TTL expiration, and session-based isolation.
* Remove or redact tokens, credentials, and personal identifiers before persisting shared context.
* Log access events with user/agent identifiers for accountability.
Ethical alignment across agents
Different agents may pursue different objectives (efficiency, coverage, creativity). To ensure coherent, responsible behavior:
* Codify system-level ethical constraints (forbidden content, safety thresholds, privacy boundaries).
* Implement centralized checks or an arbiter/supervisor agent that enforces constraints.
* Use weighted-scoring, voting, or supervisor overrides to resolve conflicts between agents.
* Route ambiguous or high‑risk outputs to human reviewers.
Bias amplification and mitigation
Bias introduced early can be amplified downstream. Mitigation techniques:
* Add bias and fairness audits at pipeline stages.
* Track sources and provenance so downstream agents can consider origin quality.
* Use diverse datasets and enforce source diversity rules for research agents.
* Introduce human review for sensitive decisions and continuously monitor for distributional drift.
Containment, sandboxing, and escalation
Plan for failure modes and minimize the blast radius:
* Execute untrusted code in sandboxes with runtime and resource limits.
* Enforce message length, API call, and retry limits.
* Escalate uncertain or high-risk actions to human operators or higher‑trust agents.
* Monitor in real time and retain structured logs for incident forensics.
Secure inter‑agent communication and validation
All inter-agent messages should be authenticated, encrypted, typed, and validated. Prefer structured formats over free text to reduce injection risks.
* Use encrypted channels (TLS) and sign messages where applicable.
* Authenticate every sender and validate authorization for requested actions.
* Prefer structured schemas (JSON + JSON Schema) to detect malformed input and reduce ambiguity.
* Sanitize payloads to defend against prompt injection and message overflow.
Example: FastAPI + Pydantic message validation and API key check
```python theme={null}
# python
from fastapi import FastAPI, Header, HTTPException
from pydantic import BaseModel
app = FastAPI()
class AgentMessage(BaseModel):
sender: str
recipient: str
kind: str
payload: dict
# Example per-agent API keys
API_KEYS = {"agent-a": "secret-token-a", "agent-b": "secret-token-b"}
def verify_api_key(x_api_key: str):
# Validate that the provided API key matches a known agent key
if x_api_key not in API_KEYS.values():
raise HTTPException(status_code=401, detail="Invalid API key")
@app.post("/message")
def receive_message(msg: AgentMessage, x_api_key: str = Header(...)):
verify_api_key(x_api_key)
# Additional authorization checks here (see authorize() below)
return {"status": "accepted", "sender": msg.sender, "recipient": msg.recipient}
```
Role-based authorization example
```python theme={null}
# python
def authorize(agent_id: str, action: str) -> bool:
role_permissions = {
"writer": {"write_document", "read_context"},
"planner": {"create_plan", "read_context"},
}
role = get_role_for_agent(agent_id) # implement your lookup
return action in role_permissions.get(role, set())
```
Operational checklist for secure, ethical MAS
Use this operational checklist as a starting point and tailor it to your domain and compliance requirements.
| Area | Minimum controls |
| ----------------- | ------------------------------------------------------------------ |
| Identity & auth | Per-agent identity, API keys or certs, mutual TLS, signed tokens |
| Authorization | RBAC, least privilege, scoped tool access |
| Communication | Encrypted channels, signed messages, schema validation |
| Memory & data | Scoped memory, redaction, TTL, session isolation |
| Execution | Sandboxed runtimes, resource limits, tool invocation controls |
| Monitoring | Structured logs, alerts, audit trails, behavioral analytics |
| Ethics & fairness | System-level constraints, bias audits, provenance tracking |
| Human oversight | Human-in-the-loop gates, escalation procedures, incident playbooks |
This checklist is an operational guide — adapt it to your domain and regulatory needs. For high-impact systems, prioritize human-in-the-loop gates, stronger isolation, and frequent security reviews.
Closing summary
Multi-agent systems deliver powerful distributed intelligence, but they introduce new security and ethical challenges. Map your threat surfaces (communication, shared memory, tool access), enforce agent identity and least privilege, validate and sandbox interactions, and implement system-level ethical constraints. Combine automated defenses with human oversight, monitoring, and structured logs to deploy MAS responsibly and at scale.
# Demo Building a Simple Chatbot
Source: https://notes.kodekloud.com/docs/AI-Agents/Building-AI-Agents/Demo-Building-a-Simple-Chatbot/page
Guide to building a simple interactive chatbot with the OpenAI Agents SDK, covering agent configuration, typed outputs, async Runner usage, environment variables, and a police sketch artist example.
Welcome back! In this lesson we’ll build a simple interactive chatbot using OpenAI’s Agents model. Before diving into code, take a few minutes to explore the OpenAI Agents SDK repository and docs — understanding where examples and patterns live will speed up development.
Start with the Quickstart and the Examples folder in the Agents SDK to see common integrations and agent patterns you can reuse. These resources demonstrate how tools, outputs, and agent behaviors are wired together.
Use the documentation as your reference for configuring agents, registering tools, and customizing outputs.
Example: typed outputs with Pydantic
Here’s a concise example showing how to define a typed output using Pydantic and create an Agent. Typed outputs make it easier to validate and consume structured results from your agent.
```python theme={null}
from pydantic import BaseModel
from agents import Agent
class CalendarEvent(BaseModel):
name: str
date: str
participants: list[str]
agent = Agent(
name="Calendar extractor",
instructions="Extract calendar events from text",
output_type=CalendarEvent,
)
```
Building the chatbot
Below we’ll create a simple interactive chatbot that:
* Loads environment variables securely (do not hard-code API keys).
* Defines an Agent with clear role-based instructions.
* Uses an asynchronous main loop to run the agent via `Runner.run`.
* Stores and displays a simple chat history.
* Supports the `history`, `exit`, and `quit` commands.
Make sure you have a `.env` file with `OPENAI_API_KEY` set, or set the environment variable in another secure way. Do not hard-code API keys in your script.
Complete chatbot script
This consolidated script demonstrates the full flow. It uses `python-dotenv` to load the API key, defines an Agent with instructions, awaits `Runner.run`, and manages conversation memory.
```python theme={null}
# chatbot_agent.py
from dotenv import load_dotenv
import os
import asyncio
from agents import Agent, Runner
# Load environment variables from .env
load_dotenv()
if not os.getenv("OPENAI_API_KEY"):
raise RuntimeError("OPENAI_API_KEY not found in environment. Add it to your .env file.")
# Define the chatbot agent
agent = Agent(
name="Police Sketch Artist",
instructions=(
"You are a police sketch artist. Collect specific details about the individual being sketched. "
"Ask follow-up questions to clarify features (hair, eyes, nose, mouth, clothing, build, distinctive marks)."
),
)
async def main():
chat_history: list[tuple[str, str]] = []
print("Police Sketch Artist chatbot. Type 'history' to view conversation, 'exit' or 'quit' to end.\n")
while True:
user_input = input("Provide specific details about the individual: ").strip()
if not user_input:
continue
# Exit commands
if user_input.lower() in ("exit", "quit"):
print("Goodbye!")
break
# Show chat history
if user_input.lower() == "history":
print("\n--- Chat History ---")
if not chat_history:
print("(no messages yet)")
for i, (u, b) in enumerate(chat_history, start=1):
print(f"{i}. You: {u}\n ChatBot: {b}\n")
print("---------------\n")
continue
# Run the agent and collect the response
result = await Runner.run(agent, user_input)
# The agent's response may be in result.final_output or result.output depending on SDK behavior
response = getattr(result, "final_output", None)
if response is None:
response = getattr(result, "output", str(result))
# Save to history and display
chat_history.append((user_input, response))
print("\nChatBot:", response)
print("To end chat, type 'exit' or 'quit'. Type 'history' to view past conversations.\n")
if __name__ == "__main__":
asyncio.run(main())
```
What this script does
* Loads environment variables safely via `python-dotenv`.
* Defines an Agent with a role-based instruction set so the model acts like a police sketch artist.
* Runs an asynchronous loop that:
* Accepts and validates user input.
* Handles `history`, `exit`, and `quit` commands.
* Invokes the agent using `await Runner.run(agent, user_input)`.
* Extracts the agent’s output (`final_output` or `output`) and appends each turn to `chat_history`.
* Prints the agent response and usage reminders.
Quick command reference
| Command | Description |
| --------------- | ------------------------------------------------------------- |
| `history` | Prints the conversation history collected during this session |
| `exit` / `quit` | Ends the chat session and exits the program |
Testing and extending the bot
Try providing details like hair color, facial features, build, clothing, or distinctive marks. The agent should ask clarifying questions to gather a structured description. Once you collect attributes, you can extend the pipeline to call an image generation API (for example, DALL·E) to create sketches from the description.
Example interaction (screenshot)
References and next steps
* OpenAI Agents guide: [https://platform.openai.com/docs/guides/agents](https://platform.openai.com/docs/guides/agents)
* OpenAI Agents SDK (examples & Quickstart): [https://github.com/openai/agents](https://github.com/openai/agents)
* python-dotenv: [https://pypi.org/project/python-dotenv/](https://pypi.org/project/python-dotenv/)
* Pydantic docs: [https://docs.pydantic.dev/latest/](https://docs.pydantic.dev/latest/)
* Images guide (DALL·E): [https://platform.openai.com/docs/guides/images](https://platform.openai.com/docs/guides/images)
Thank you for reading.
# Demo Setting Up Development Environment
Source: https://notes.kodekloud.com/docs/AI-Agents/Building-AI-Agents/Demo-Setting-Up-Development-Environment/page
Guide to setting up a local Jupyter development environment, securing an OpenAI API key with a .env, and using GitHub for version control and safe commits
Welcome to the first demo lesson.
In this guide you'll set up a local development environment for working with Jupyter Notebook and GitHub, then securely store an OpenAI API key for use in your notebooks. Jupyter Notebook is ideal for step-by-step prototyping, visualization, and interactive documentation — particularly useful for data science, machine learning, and teaching. Pairing Jupyter with GitHub gives you version control, collaboration, and cloud backup so your notebooks remain reproducible and shareable.
This walkthrough covers:
* Installing Anaconda to run Jupyter
* Launching and using Jupyter Notebook (kernels, running cells, common pitfalls)
* Creating a secure `.env` file for your API key and loading it in Python
* Creating a GitHub repository and committing your project safely
***
## 1) Install Anaconda (to run Jupyter)
1. Visit the Anaconda distribution page: [https://www.anaconda.com/products/distribution](https://www.anaconda.com/products/distribution)
2. Download the free distribution for your operating system.
3. You can skip account registration and proceed with the installer.
4. After installation, launch Anaconda Navigator to access Jupyter Notebook and other tools.
***
## 2) Launching Jupyter Notebook
* Start Jupyter Notebook from Anaconda Navigator (or run `jupyter notebook` from a terminal). It opens in your default browser at a local URL such as `http://localhost:8888/tree`.
* Create a project folder: click New → New Folder, rename it (e.g., `Demo Project`) and open it.
* Create a new notebook inside the folder: New → Python 3 (or an available kernel).
* Rename the notebook by clicking the title (e.g., change "Untitled" to `Demo`).
The menu bar contains File, Edit, View, Run, Kernel, Settings, Help. The toolbar provides quick actions: run cell, move cells, cut/copy/paste, restart kernel, etc.
### Kernel & run controls — quick reference
| Action | What it does |
| ------------ | -------------------------------------------------------------------------------------- |
| Interrupt | Stops currently executing code (useful for infinite loops or long-running operations). |
| Restart | Restarts the kernel and clears in-memory state (variables, imports). |
| Shutdown | Ends the kernel session. |
| Run cell (▶) | Executes the current cell and advances depending on the option chosen. |
Tip: If your notebook behaves unexpectedly (old variables, mismatched outputs), use Kernel → Restart & Clear Output to get a clean runtime and reproduce results deterministically.
***
## 3) Examples — running cells and managing the kernel
Infinite loop example (run with caution):
```python theme={null}
while True:
print("Hi")
```
If you execute this, it will continually print until you interrupt the kernel (Kernel → Interrupt or the stop button).
Common error example (Python is case-sensitive):
```python theme={null}
while true:
print("hi")
```
This raises a `NameError` because `true` (lowercase) is not defined in Python. The correct boolean literal is `True`.
### Cell execution order and kernel state
Cells execute in the kernel's current state. If you modify a later cell but do not re-run it, the kernel will still use the previously executed value.
Example:
```python theme={null}
foo = 1 + 1
print(foo) # outputs: 2
```
If you later change another cell to:
```python theme={null}
foo = 1 + 1 + 1
# (but do not run this cell)
```
and then re-run the `print(foo)` cell without running the updated assignment cell, the output remains `2`. To update the kernel state, run the assignment cell or restart and re-run the notebook in order.
Restarting the kernel (Kernel → Restart & Clear Output) clears state and outputs and is useful to confirm reproducibility.
***
## 4) Store a secure `.env` file for your API key
Keeping secrets outside source control is essential. Create a `.env` file locally and never commit it.
Create `.env` programmatically (replace `YOUR_OPENAI_API_KEY` with your real key after you obtain it):
```python theme={null}
with open(".env", "w") as f:
f.write("OPENAI_API_KEY=YOUR_OPENAI_API_KEY")
```
Add `.env` to `.gitignore` before committing:
```text theme={null}
.env
```
Example `.env` content (do not paste real keys into shared or public files):
```text theme={null}
OPENAI_API_KEY=sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```
Do not commit `.env` or your API keys to GitHub. Keep secrets out of version control and use environment-specific secret management in production.
***
## 5) Getting your OpenAI API key
1. Go to the OpenAI dashboard: [https://platform.openai.com/account/api-keys](https://platform.openai.com/account/api-keys)
2. Log in or create an account.
3. From the dashboard, open Settings (cogwheel) → API keys.
4. Create a new secret key, give it a descriptive name (e.g., `Demo API Key final`), and copy it immediately — the secret is shown only once.
After creating the key, paste it into your `.env` file (or update the file manually).
***
## 6) Loading environment variables in Python
Install python-dotenv if not already installed:
```bash theme={null}
pip install python-dotenv
```
Load the `.env` and verify the key is present:
```python theme={null}
from dotenv import load_dotenv
import os
load_dotenv()
print(os.getenv("OPENAI_API_KEY") is not None) # Should print: True
```
***
## 7) Add a small code test to the notebook
Add a few simple cells to confirm everything runs:
```python theme={null}
print(1)
print("Hello World")
```
***
## 8) Set up a GitHub repository and commit safely
1. Sign in to GitHub: [https://github.com](https://github.com)
2. Create a new repository (e.g., `Demo-API-Setup`). Choose private if you prefer and add a README.
Confirm `.gitignore` includes `.env` before committing.
Quick Git commands (run from your project root):
| Command | Purpose |
| --------------------------------------------------------------------------- | -------------------------------------------------- |
| `git init` | Initialize a new repository |
| `git add .` | Stage all files (ensure `.gitignore` is set first) |
| `git commit -m "Initial commit"` | Create the first commit |
| `git branch -M main` | Rename the default branch to `main` |
| `git remote add origin https://github.com/your-username/Demo-API-Setup.git` | Add your remote (replace with your URL) |
| `git push -u origin main` | Push commits to GitHub and set upstream |
Replace the remote URL with your repository's HTTPS or SSH URL.
***
## Wrap-up
You have completed the essential setup:
* Installed Anaconda and launched Jupyter Notebook.
* Learned to manage kernels and run cells reliably.
* Created and loaded a secure `.env` file for your OpenAI API key using `python-dotenv`.
* Created a GitHub repository and prepared your project to avoid committing secrets.
Use this workflow for future projects to keep secrets safe, ensure reproducibility, and maintain clear version control for notebooks.
***
## Links and references
* Jupyter: [https://jupyter.org](https://jupyter.org)
* Anaconda distribution: [https://www.anaconda.com/products/distribution](https://www.anaconda.com/products/distribution)
* OpenAI API keys: [https://platform.openai.com/account/api-keys](https://platform.openai.com/account/api-keys)
* python-dotenv: [https://pypi.org/project/python-dotenv/](https://pypi.org/project/python-dotenv/)
* GitHub: [https://github.com](https://github.com)
# Development Environment Overview
Source: https://notes.kodekloud.com/docs/AI-Agents/Building-AI-Agents/Development-Environment-Overview/page
Overview of using Jupyter and GitHub to build reproducible, collaborative development environments and workflows for AI agent engineering.
Welcome back.
This lesson reviews the development-environment landscape for AI agent engineering, focusing on Jupyter Notebook and GitHub. We'll explain why a reproducible, collaborative environment matters for agents and provide practical guidance, commands, and patterns you can apply immediately.
We’ll cover:
* The role of development environments in AI agent engineering
* What Jupyter is and why it fits agent workflows
* Key Jupyter features for AI workflows
* What GitHub is and why it matters for agents
* GitHub features for collaboration and CI/CD
* Version-control practices for agent projects
* How to integrate Jupyter with GitHub (plus commands and examples)
* A concrete end-to-end example workflow
* Common pitfalls and how to avoid them
* Useful tools and extensions for Jupyter and GitHub
* Security and best practices
* Summary and next steps
AI agents combine prompts, tool calls, LLM invocations, and memory/state management. A solid development environment accelerates experimentation, ensures reproducibility, and enables safe collaboration. In short, Jupyter and GitHub are not just conveniences — they are foundational for building, debugging, and iterating on agent systems.
Why development environments matter for agents
* Centralize code, experiments, and documentation so results are reproducible and auditable.
* Enable rapid, iterative testing (change prompts or parameters and see results immediately).
* Support automated testing, CI/CD, and controlled rollouts as agents evolve.
* Reduce onboarding friction by standardizing development environments across teams.
## Jupyter: overview and why it fits agent workflows
Jupyter is an open-source, interactive environment that runs in the browser and combines executable code, outputs, visualizations, and Markdown documentation in a single notebook file (`.ipynb`). It’s a natural fit for agent development because:
* Incremental, cell-based execution enables fast experimentation: tweak prompts, embeddings, or tool calls and inspect responses without rerunning unrelated initialization.
* The mixed code/Markdown format is ideal for documenting design choices, hypotheses, and results alongside runnable code.
* Jupyter supports many languages (Python, Julia, R), but Python is the dominant choice for LLM, embeddings, and agent toolchains.
* You can import SDKs and libraries (for example, OpenAI SDKs and LangChain) directly in notebooks to prototype integrations quickly.
Resources:
* [Introduction to OpenAI](https://learn.kodekloud.com/user/courses/introduction-to-openai)
* [LangChain course](https://learn.kodekloud.com/user/courses/langchain)
### Key Jupyter features for agent development
* Cell-based execution for incremental testing of code that calls external APIs or manipulates memory.
* Inline visualizations and stdout/stderr outputs to inspect agent behavior and tool responses.
* Markdown cells to explain experiment intent, assumptions, and conclusions next to code.
* Extensible ecosystem (JupyterLab, nbextensions, VS Code/Jupyter plugins) for navigation, Git integration, and productivity.
## GitHub: why it matters for agent projects
GitHub, built around Git, is the standard platform for collaborative development and version control. For agent projects it provides:
* A complete history of changes so you can restore previous prompt states, tool configs, or decision logic.
* Pull requests and issue tracking for asynchronous collaboration and structured code review.
* Automation through GitHub Actions for CI, testing, and deployment pipelines.
* Integration with assistive tools like GitHub Copilot to speed development and refactoring.
* A centralized place to publish and discover open-source agent frameworks and integrations.
### GitHub features especially helpful for AI projects
* Fine-grained change history for code, prompts, and configuration.
* Branching and pull requests to isolate experiments and review behavior changes.
* GitHub Actions for automated linting, unit tests, notebook validation, and deployments.
* Issue templates, project boards, and discussions to track experiments, evaluations, and reproducibility tasks.
## Version control practices for agent projects
Version control in agent projects goes beyond tracking source files — it manages evolving prompts, toolchains, and data dependencies. Best practices:
* Use branches to isolate experiments and new capabilities.
* Write descriptive commit messages that explain why a prompt or architecture changed (not just what changed).
* Use code reviews to discuss behavioral differences and regressions.
* Track experiments and model artifacts separately (see DVC / MLflow below).
## Integrating Jupyter with GitHub — practical tips and commands
Notebooks are JSON files (`.ipynb`) and can produce noisy diffs because they store outputs. Use the following strategies to keep repositories clean and maintainable.
Recommended tooling and patterns:
* Remove outputs before committing:
* Use `nbstripout` to automatically clear outputs on commit.
* Example installation and activation:
```bash theme={null}
pip install nbstripout
nbstripout --install
```
* Use pre-commit hooks for consistent repo hygiene:
* Example `.pre-commit-config.yaml` snippet:
```yaml theme={null}
repos:
- repo: https://github.com/kynan/nbstripout
rev: v0.5.0
hooks:
- id: nbstripout
```
* Install:
```bash theme={null}
pip install pre-commit
pre-commit install
```
* Use Git LFS for large artifacts (embeddings, model checkpoints):
```bash theme={null}
git lfs install
git lfs track "*.onnx"
git add .gitattributes
```
* Use `papermill` for parameterized runs (turn notebooks into reproducible, parameter-driven jobs):
```bash theme={null}
pip install papermill
papermill input.ipynb output.ipynb -p param_name value
```
* Use `nbdime` for notebook-aware diffs and merges:
```bash theme={null}
pip install nbdime
nbdime config-git --enable
```
Best UX workflow:
* Prototype in a notebook.
* Extract stable code into Python modules or packages.
* Keep notebooks for orchestration, examples, and documentation; put production logic into versioned modules.
* Use GitHub Codespaces, JupyterLab, or VS Code to synchronize work across collaborators.
## Example end-to-end agent development workflow
1. Prototype in Jupyter:
* Create prompt templates, test API calls, and log results in Markdown and output cells.
2. Stabilize logic:
* Extract reusable code into modules (e.g., `agents/core.py`, `agents/tools.py`) and add unit tests.
3. Commit and clean:
* Commit notebooks and scripts to GitHub. Use `.gitignore` to exclude secrets and `nbstripout` to strip outputs.
4. Branch and experiment:
* Use feature branches per experiment, then open pull requests to review behavior changes.
5. Automate:
* Use GitHub Actions to run linting, unit tests, and notebook validation on PRs.
6. Deploy and test:
* Deploy to staging and run integration tests before promoting to production.
Common Git commands for this flow:
```bash theme={null}
git checkout -b feature/prompt-refactor
git add .
git commit -m "Refactor prompt to improve slot-filling"
git push origin feature/prompt-refactor
```
## Common pitfalls and mitigations
* Large outputs and binary artifacts increase repository size and create noisy diffs.
* Mitigation: enable `nbstripout`, use Git LFS, and clear outputs before committing.
* Merge conflicts in `.ipynb` files due to JSON format.
* Mitigation: break code into modules, do smaller, frequent merges, and use `nbdime` to resolve notebook diffs.
* Accidental commit of sensitive data (API keys, tokens).
* Mitigation: put secrets in `.env`, add them to `.gitignore`, use secret scanning, and rotate credentials if exposed.
* Monolithic notebooks mixing experiments and production logic.
* Mitigation: modularize and keep notebooks primarily for orchestration and documentation.
Avoid committing credentials or large outputs. Use `.gitignore`, `.env` files, secret scanners, `nbstripout`, and Git LFS to keep your repository secure and performant.
## Tools and extensions to improve workflow
* nbextensions: code folding, variable inspectors, table of contents for classic notebooks.
* JupyterLab: modern multi-tab interface with terminals and rich extensions.
* GitHub Codespaces: cloud dev environments with Jupyter pre-installed for consistent environments.
* VS Code + Jupyter plugin: edit notebooks locally with robust Git and debugging support.
* DVC and MLflow: version and track datasets, models, and experiments.
Useful quick-reference table
| Tool / Feature | Purpose | Example / Command |
| -------------- | ---------------------------- | ----------------------------------------------------- |
| `nbstripout` | Remove outputs before commit | `nbstripout --install` |
| `pre-commit` | Enforce repository hooks | `pre-commit install` |
| Git LFS | Track large model artifacts | `git lfs install` |
| `papermill` | Parameterized notebook runs | `papermill in.ipynb out.ipynb -p learning_rate 0.001` |
| `nbdime` | Notebook-aware diffs/merges | `nbdime config-git --enable` |
| DVC / MLflow | Experiment & data tracking | See DVC and MLflow docs |
## Security and best practices (brief)
* Never hard-code API keys in notebooks. Use environment variables, `.env` files, or secret managers.
* Add tests and linters to CI/CD to catch regressions in prompt handling and tool integrations.
* Modularize production logic into versioned packages; use notebooks for experiments and documentation.
* Keep a CHANGELOG or use detailed commit messages to record rationale for prompt and architecture changes.
Best practices summary: modularize code, use branches and pull requests, log key changes, and never commit secrets. These habits improve reproducibility, collaboration, and long-term maintainability of agent projects.
## Summary and next steps
Jupyter and GitHub together form a powerful foundation for building AI agents:
* Use Jupyter notebooks for rapid prototyping, interactive debugging, and documentation.
* Use GitHub for version control, code review, CI/CD, and collaboration.
* Adopt tooling like `nbstripout`, `nbdime`, GitHub Actions, and Git LFS to keep repos clean and reproducible.
* Move stable logic into modular Python packages and track experiments with DVC or MLflow.
Actionable next steps:
* Add `nbstripout` and a `pre-commit` config to your repo.
* Start a branch-based workflow for experiments.
* Configure a simple GitHub Actions workflow to run linting and tests on PRs.
* Create a short README that documents how to run notebooks, tests, and parameterized runs.
By investing in these development practices now, you make agent engineering faster, safer, and more collaborative as your project grows.
# Understanding Conversational AI Theories and Design
Source: https://notes.kodekloud.com/docs/AI-Agents/Building-AI-Agents/Understanding-Conversational-AI-Theories-and-Design/page
Explains conversational AI concepts, components, design theories, architectures, approaches, and best practices for building chatbots and conversational agents with NLU, dialogue management, memory, and tools
Welcome back.
This lesson introduces conversational AI: what it encompasses, how chatbots differ from conversational agents, the linguistic and cognitive theories that shape design, and the practical components, patterns, and best practices for building robust conversational systems.
We’ll cover:
* What conversational AI includes and why it matters
* Chatbot vs conversational agent
* Conversation theories: turn-taking, grounding, and intent
* Core system components: NLU, Dialogue Manager, NLG, Memory/Context, and Tools/APIs
* Rule-based, LLM-based, and hybrid approaches
* Intent recognition, dialogue management, and state/memory strategies
* Conversation design: prompts, fallbacks, tone, and UX
* Use cases and design best practices for agent systems
Conversational AI is the interface between people and software agents. It enables systems to understand user intent, manage multi-turn exchanges, and produce helpful, context-aware responses. For service-oriented and interactive roles, agents must communicate clearly and empathetically — good conversational design is essential for systems that feel natural, reliable, and trustworthy.
***
## What is Conversational AI?
Conversational AI refers to technologies that allow machines to converse with humans using natural language. This includes chatbots, voice assistants, multimodal dialogue systems, and autonomous AI agents. The fundamental subcomponents are:
* Natural Language Understanding (NLU)
* Intent recognition and entity extraction
* Natural Language Generation (NLG)
For agent systems, conversational AI provides the interaction layer for delegation flows, information retrieval loops, and multi-step task execution.
***
## Chatbots vs Conversational Agents
* Chatbots: Typically scripted, built for defined flows (menu-driven IVR, decision trees). Best suited to predictable, structured tasks.
* Conversational agents: More autonomous. Accept broader inputs, maintain memory, reason about goals, and can take actions across systems (for example: gather details, book a pickup, and confirm in one session).
Conversational agents are an evolution of chatbots, combining dialogue skills with reasoning, memory, and action execution.
***
## Core Conversation Theories That Inform Design
Designers borrow from linguistics and cognitive psychology. The main concepts to apply:
* Turn-taking: Conversations are organized into alternating turns. Agents must detect when to speak, when to listen, and when to yield.
* Grounding: Shared understanding is built incrementally. Agents should confirm critical facts and request clarifications when necessary.
* Intent theory: Utterances are goal-driven. Agents must infer the user’s intention (the goal behind the text), not just parse literal words.
These theories guide how systems manage relevance, timing, and cooperative exchanges.
***
## Core System Components
A typical conversational AI architecture includes the following components and responsibilities:
| Component | Primary responsibility | Example outputs |
| ---------------- | ------------------------------------------------------------- | -------------------------------------------- |
| NLU | Parse text or speech, classify intent, extract entities/slots | `book_flight`, `{destination: "Tokyo"}` |
| Dialogue Manager | Decide next action from policies (ask, call API, end) | `ask_for_date`, `invoke_booking_api` |
| NLG | Generate fluent, contextual responses | "Your flight to Tokyo is booked for May 10." |
| Memory / Context | Track session state and optionally long-term user data | `session_slots`, `user_preferences` |
| Tools / APIs | Perform external actions (calendar, DB, ticketing) | calendar API call, booking endpoint |
***
## System Architecture and Integration
Enterprise platforms typically route users (voice, chat, web, mobile) through secure endpoints into a conversational experience layer that handles speech recognition, session routing, and orchestration. The core NLP/AI platform (NLU, LLM or ML engine, semantic search) drives interpretation and responses. A central knowledge store holds domain metadata, training data, and persistent memory. Integration hubs connect backend services (CRM, ticketing), while dashboards provide monitoring and tuning.
Key integration points:
* Authentication and secure endpoints
* Orchestration and session management
* Knowledge retrieval and tool invocation
* Feedback and telemetry for continuous improvement
***
## Rule-based vs LLM-based Bots (and Hybrids)
* Rule-based bots: Use explicit rules, patterns, and decision trees. Predictable, transparent, and easy to debug—but brittle outside of expected flows.
* LLM-based bots: Use large language models to interpret and generate text. Flexible and better at handling open-domain or unstructured queries but probabilistic and prone to hallucination without grounding.
Hybrid architectures are common in production: use LLMs for language understanding and generation while enforcing rule-based fallbacks and constraints for safety-critical actions.
To summarize trade-offs:
| Attribute | Rule-based | LLM-based |
| ------------------------------ | --------------------------- | ------------------------------------------------- |
| Predictability | High | Lower (probabilistic) |
| Transparency | High | Opaque |
| Compute needs | Low | High |
| Handling of open-ended queries | Limited | Strong |
| Best for | Form-like flows, compliance | Virtual assistants, synthesis, creative responses |
Resource and use-case differences are important when selecting an approach:
Useful references:
* Read about practical LLM design patterns in prompt engineering and retrieval-augmented generation.
* Consider [vector databases](https://learn.kodekloud.com/user/courses/vector-database-for-genai) for semantic memory storage.
***
## Intent Recognition and the Dialogue Manager
Intent recognition converts a user utterance into a structured intent (e.g., `cancel_order`, `check_balance`, `book_flight`) and extracts entities. The Dialogue Manager then applies policies—rule-based, learned, or hybrid—to select the next action:
* Ask for missing information (slot-filling)
* Call an external API or tool
* Confirm completion and close the task
This flow is central to multi-turn interactions where persistent context is required.
***
## State Management and Memory
Agents typically use two memory horizons:
* Short-term / session memory: Tracks the current conversation state (filled slots, recent prompts, temporary context).
* Long-term memory: Persists across sessions for personalization (user preferences, past transactions). Long-term memory is often stored in semantic stores such as vector databases for retrieval.
Well-managed state enables follow-ups, corrections, personalization, and coherent multi-step tasks.
***
## Context Pipeline for LLM-driven Agents
A standard LLM-driven agent context pipeline:
1. Context manager gathers relevant data from persistent stores (session state, long-term memory, external sources).
2. The compiled context is prepared as the LLM input (context window).
3. The LLM generates an action or response.
4. Any state updates are written back to the persistence layer.
This cycle maintains continuity and allows agents to adapt while remaining coherent.
***
## Conversation Design: Prompts, Tone, and Fallbacks
Design practices that improve task success and user satisfaction:
* Keep prompts concise and informative.
* Match tone to the domain: casual for retail, professional for finance or healthcare.
* Provide explicit fallbacks and clarifying prompts: e.g., “I didn’t understand that. Did you mean X or Y?”
* Design for edge cases and graceful failures—avoid dead-ends.
* Partition memories by agent role to avoid leaking irrelevant or sensitive data.
* Give agents a consistent personality (cheerful, professional) to increase trust.
* Log and analyze interactions to iteratively improve prompts and policies.
Design for both the ideal path and common deviations. Short confirmations and clarifying questions reduce misunderstandings and improve task completion rates.
***
## Use Cases and Agent Ecosystems
Common applications:
* Support agents: Diagnose issues, guide troubleshooting, and escalate when needed.
* Onboarding agents: Collect configuration data and guide initial setup flows.
* System interfaces: Provide conversational front-ends to backend services.
* Agent chains: One agent collects/refines information and passes it to another for synthesis or execution.
These patterns enable modular, chat-driven workflows that can achieve complex outcomes.
***
## Best Practices and Resilience
Practical guidance for production-grade systems:
* Limit context to what’s relevant: oversized context windows increase costs and complexity.
* Implement structured fallbacks and clarifiers for ambiguous inputs.
* Separate memories by agent role to reduce leakage of irrelevant or sensitive data.
* Instrument consistent logging and monitoring, especially during early rollout.
* Monitor for failure modes such as hallucination, privacy leaks, or unsafe actions and implement rule-based safeguards.
[LLM-driven systems](https://learn.kodekloud.com/user/courses/ai-agents-fundamentals) can hallucinate or infer incorrect facts. Use grounded retrieval, verification, and rule-based constraints for critical actions and data-sensitive tasks.
***
## Summary
Conversational AI blends linguistic theory, system engineering, and user-centered design. Applying turn-taking, grounding, and intent principles improves conversational behavior. Typical architectures combine NLU, dialogue management, NLG, and memory stores, while integration hubs and dashboards enable production operations. Choose rule-based, LLM-based, or hybrid architectures based on task complexity, risk tolerance, and available resources. Robust state management, concise prompts, fallbacks, and ongoing telemetry are essential to build reliable, trustworthy conversational agents.
Further reading and resources:
* Conversational AI fundamentals and design patterns
* Prompt engineering and retrieval-augmented generation
* Vector databases and semantic retrieval for long-term memory
# Course Introduction
Source: https://notes.kodekloud.com/docs/AI-Agents/Introduction/Course-Introduction/page
A practical course teaching developers how to design, build, and deploy autonomous AI agents using frameworks, tools, and hands-on labs
AI agents are transforming how we build software, automate work, and enhance human productivity. These intelligent systems can reason, act, and collaborate to complete complex tasks — from customer support assistants to autonomous research agents. Leading companies such as Microsoft, OpenAI, Google, and Meta are shipping agent-driven products (Copilot, ChatGPT, Gemini, Meta AI) that showcase how agents improve workflows and create new application categories.
Welcome to the AI Agents course from KodeKloud. I’m Gav Ridgeway, and I’ll guide you through designing, building, and deploying autonomous AI agents. This course is practical and hands-on, aimed at developers, data scientists, and anyone curious about agent-based systems.
What you’ll gain:
* A clear definition of AI agents and their main categories.
* Practical knowledge of core technologies (embeddings, vector DBs, evaluation).
* Experience designing agent architectures and multi-agent interactions.
* Hands-on labs using frameworks like LangChain, CrewAI, AutoGen, and MetaGPT.
* Techniques for connecting agents to external APIs and tools (OpenAI, community APIs).
* Best practices for scaling, monitoring, and evaluating agent systems.
## Course outline (high-level)
| Module | Topics covered | Outcome |
| --------------- | ------------------------------------------ | ------------------------------------------- |
| Foundations | What is an agent, agent types, ethics | Understand trade-offs and governance needs |
| Core tech | Embeddings, vector DBs, retrieval, eval | Build retrieval-augmented agents |
| Architectures | Single-agent vs multi-agent, orchestration | Design system architecture diagrams |
| Frameworks | LangChain, CrewAI, AutoGen, MetaGPT | Implement agent flows and chains |
| Tooling & APIs | Integrating search, APIs, and tools | Extend agent capabilities via plugins/tools |
| Projects & Labs | Task-driven and multi-role agents | Deploy a working agent pipeline |
Useful references:
* OpenAI API docs: [https://platform.openai.com/docs](https://platform.openai.com/docs)
* LangChain: [https://langchain.com](https://langchain.com)
* MetaGPT: [https://github.com/metagpt/metagpt](https://github.com/metagpt/metagpt)
## Prerequisites and setup
Before running agent examples, ensure your environment variables (API keys, base URLs) are configured and never committed to source control.
Store secrets (API keys, tokens) in a `.env` file and load them with `python-dotenv` during development. Use environment variables for CI/CD and secret managers in production.
Never commit secrets to public repositories. Improper handling of API keys can lead to unauthorized usage and unexpected costs.
Example: load environment variables with dotenv
```python theme={null}
from dotenv import load_dotenv
import os
# Loads variables from .env into the environment during local development
load_dotenv()
# Verify that an API key is present (prints True/False)
print(bool(os.environ.get("OPENAI_API_KEY")))
```
## Simple async agent (illustrative)
This example shows a minimal async agent pattern. Framework APIs differ — adapt to LangChain, CrewAI, AutoGen, or your chosen SDK.
```python theme={null}
import asyncio
from agents import Agent, Runner, WebSearchTool
fav_stock = ["Google", "Apple", "Nvidia"]
async def main():
agent = Agent(
name="Stock News Expert",
instructions=(
"You are a stock news expert. Review recent news for the given companies "
"and summarize key events."
),
tools=[WebSearchTool()] # Provide any necessary tools as a list
)
runner = Runner(agent=agent)
# Run the agent on the list of stock names (frameworks may vary)
await runner.run(tasks=fav_stock)
if __name__ == "__main__":
asyncio.run(main())
```
## Utility example — language and emotion detection (OpenAI Chat API)
This synchronous example demonstrates how to call a chat model to parse language and emotional tone. Adapt to your SDK version (e.g., the OpenAI Python SDK or HTTP API). See OpenAI Chat API docs: [https://platform.openai.com/docs/api-reference/chat](https://platform.openai.com/docs/api-reference/chat)
```python theme={null}
import os
import re
import openai
openai.api_key = os.environ.get("OPENAI_API_KEY")
def analyze_language_and_emotion(text: str) -> dict:
system_msg = (
"You are an AI that analyzes messages. Detect the language (e.g., English, French) "
"and describe the emotional tone in one word (e.g., joyful, sad, angry, professional, excited, persuasive). "
"Respond in the format:\nLanguage: \nEmotion: "
)
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[
{"role": "system", "content": system_msg},
{"role": "user", "content": f"Here is the message:\n{text}"}
],
temperature=0.3
)
content = response["choices"][0]["message"]["content"].strip()
language_match = re.search(r"Language:\s*(\w+)", content, re.IGNORECASE)
emotion_match = re.search(r"Emotion:\s*(\w+)", content, re.IGNORECASE)
return {
"language": language_match.group(1) if language_match else "Unknown",
"emotion": emotion_match.group(1) if emotion_match else "Unknown"
}
```
## Labs, demos, and practical projects
Hands-on labs guide you from local prototypes to deployable agents. You’ll practice building task-driven agents, multi-role simulations, and integrating external tools and APIs. Labs emphasize reproducibility and safe testing practices.
## Quick client initialization (OpenAI Python SDK)
A compact example to initialize an SDK client. If you use an async client or a different vendor, adapt accordingly.
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ.get("OPENAI_API_KEY"),
base_url=os.environ.get("OPENAI_API_BASE") # optional custom base URL
)
```
## Best practices and next steps
* Use small iterative experiments to validate agent behaviors before scaling.
* Log agent actions and decisions for auditing and debugging.
* Evaluate agents with both automated metrics and human review to ensure reliability and safety.
* Integrate secret management, rate-limiting, and cost controls early in your deployment pipeline.
At KodeKloud, we foster an active community where you can ask questions, share code, and collaborate on projects. Join peers and instructors to accelerate your learning.
Let's begin this journey — build with curiosity and guardrails, and unlock what AI agents can do for you.
# Demo Building a News Aggretor Using WebSearchTool
Source: https://notes.kodekloud.com/docs/AI-Agents/Practical-Projects/Demo-Building-a-News-Aggretor-Using-WebSearchTool/page
Guide to building a stock news aggregator that searches the web for company updates, summarizes one sentence per stock, classifies sentiment, and exports results to Excel
Welcome back.
In this lesson we build a lightweight stock news tracker that:
* searches the web for the latest updates on a list of companies,
* summarizes one interesting story for each company,
* analyzes the sentiment of that summary (positive / neutral / negative),
* exports the aggregated results into a clean Excel file for further review.
Create a new notebook (or script) and name it `Stock News Pro`. Save it and make sure your environment contains your [OpenAI API key](https://platform.openai.com/account/api-keys) (for example, in a `.env` file).
Make sure your `.env` contains a valid [API key](https://platform.openai.com/account/api-keys) (for example `OPENAI_API_KEY=...`). This lesson uses an agents package that provides an Agents SDK and a `WebSearchTool` to perform live web queries.
## Overview
This guide is organized into four clear steps:
1. Setup and imports
2. Main logic (single async function that performs search, summarize, classify, and collect)
3. Running the script (script vs. notebook)
4. Output format and where files are saved
Follow the sections below to implement the tracker end-to-end.
## 1 — Setup and imports
Load environment variables and import the core libraries:
```python theme={null}
# python
from dotenv import load_dotenv
import os
load_dotenv() # loads environment variables from .env into os.environ
```
Then import the remaining dependencies:
```python theme={null}
# python
import asyncio
import pandas as pd
from pathlib import Path
from agents import Agent, Runner, WebSearchTool, trace
```
Define the list of favorite stocks we want to track:
```python theme={null}
# python
fav_stocks = ["Google", "Apple", "Nvidia"]
```
## 2 — Main logic
Below is a single consolidated async function that:
1. Creates an `Agent` with the `WebSearchTool`.
2. For each stock:
* searches the web and requests one recent update in a single sentence,
* extracts the summary,
* asks the agent to classify sentiment (positive / neutral / negative),
* maps the sentiment to an emoji,
* extracts a source link if available,
* appends the result to the `results` list.
3. Converts the list to a pandas `DataFrame` and exports it to Excel (both the current working directory and the user's Downloads folder when possible).
```python theme={null}
# python
async def main():
agent = Agent(
name="Stock News Expert",
instructions="You are a stock news expert. Review the most recent news on these stocks/companies and provide concise answers.",
tools=[WebSearchTool(user_location={"type": "approximate", "city": "New York City"})],
)
results = []
with trace("Stock news summary"):
for stock in fav_stocks:
query = f"Search the web for news about '{stock}' and give me 1 recent update in a sentence."
result = await Runner.run(agent, query)
summary = (result.final_output or "").strip()
# Ask for sentiment and expect only: positive, neutral, or negative
sentiment_query = (
f"What is the sentiment of this sentence? '{summary}' "
"Answer only with: positive, neutral, or negative."
)
sentiment_result = await Runner.run(agent, sentiment_query)
sentiment = (sentiment_result.final_output or "").strip().lower()
# Map sentiment to an emoji for quick visual scanning
sentiment_emoji = {
"positive": "✅",
"neutral": "😐",
"negative": "❌",
}
sentiment_display = f"{sentiment.capitalize()} {sentiment_emoji.get(sentiment, '')}"
# Extract a link from sources if present
link = None
if hasattr(result, "sources") and result.sources:
try:
# result.sources is often a list of source dicts; attempt to get a URL
if isinstance(result.sources, list) and result.sources:
link = result.sources[0].get("url")
elif isinstance(result.sources, dict):
link = result.sources.get("url")
except Exception:
link = None
results.append({
"Stock": stock,
"News": summary,
"Sentiment": sentiment_display,
"Link": link
})
# Convert results to DataFrame and save to Excel
df = pd.DataFrame(results)
filename = "Stock_News_Summary_Pro.xlsx"
df.to_excel(filename, index=False)
print(f"News saved to {filename}")
# Also save a copy to the user's Downloads folder (convenience)
downloads_path = Path.home() / "Downloads" / filename
try:
df.to_excel(downloads_path, index=False)
print(f"Saved to {downloads_path}")
except Exception as e:
print(f"Could not save to Downloads: {e}")
```
The script performs live web searches using the `WebSearchTool`. Expect variability in outputs and occasional missing source links. Monitor API usage and rate limits for your API key to avoid unexpected charges.
## 3 — Running the script
If you are running this as a standalone script, start the async function like this:
```python theme={null}
# python
if __name__ == "__main__":
asyncio.run(main())
```
If you are in a Jupyter notebook, run the coroutine directly with:
```python theme={null}
# python
await main()
```
## 4 — What the output looks like
When the script finishes you will see the Excel files (if both saves succeeded):
| Location | Filename |
| ------------------------- | ----------------------------- |
| Current working directory | `Stock_News_Summary_Pro.xlsx` |
| User's Downloads folder | `Stock_News_Summary_Pro.xlsx` |
Each Excel file contains the following columns:
| Column | Description | Example |
| --------- | ------------------------------------------------------ | ----------------------------------------- |
| Stock | The company name being tracked | `Apple` |
| News | The one-sentence recent update returned by the agent | `Apple announces new AI features in iOS.` |
| Sentiment | Sentiment label with emoji (e.g., "Positive ✅") | `Positive ✅` |
| Link | Source URL if available (`None` or blank if not found) | `https://example.com/news/article` |
This output is ready for sorting, filtering, or importing into other analytics tools.
## Links and references
* [OpenAI API keys](https://platform.openai.com/account/api-keys)
* Pandas documentation: [https://pandas.pydata.org/docs/](https://pandas.pydata.org/docs/)
* Python asyncio: [https://docs.python.org/3/library/asyncio.html](https://docs.python.org/3/library/asyncio.html)
That’s it — you now have a working stock news tracker that searches headlines, summarizes one recent update per company, classifies sentiment, and exports the results to Excel for later analysis. Hope you enjoyed this lesson.
# Demo Exploring Computer Tools Playwright
Source: https://notes.kodekloud.com/docs/AI-Agents/Practical-Projects/Demo-Exploring-Computer-Tools-Playwright/page
Shows how to build a Python Playwright browser agent that renders pages, captures screenshots, scrapes text, and summarizes content with GPT-4 in a Jupyter notebook.
Welcome back.
In this lesson we'll build a compact, practical AI browser agent using Python and Playwright. This example shows how to programmatically render a page, capture a screenshot, extract on-page text, and summarize it with GPT-4. Before you begin, review the Playwright documentation for installation details, browser support, device descriptors, and advanced selectors.
Install Playwright and its browser binaries once per environment. In Jupyter notebooks, prefix shell commands with `!`.
## Installation and imports
Run these commands in a Jupyter notebook cell to install Playwright, its browser binaries, and python-dotenv:
```python theme={null}
!pip install playwright python-dotenv --quiet
!playwright install --quiet
```
Quick reference — common setup commands:
| Task | Command |
| ------------------------------ | ----------------------------------------------- |
| Install packages | `!pip install playwright python-dotenv --quiet` |
| Install Playwright browsers | `!playwright install --quiet` |
| Load environment vars (Python) | `from dotenv import load_dotenv; load_dotenv()` |
Now import the modules you will use and load environment variables:
```python theme={null}
from dotenv import load_dotenv
load_dotenv()
import os
import asyncio
import openai
from IPython.display import Image, display
```
Keep your [OpenAI API key](https://platform.openai.com/docs/guides/api-keys) in an environment variable (for example, `OPENAI_API_KEY`). Set the key for the `openai` library as shown below.
Never commit API keys to source control. Use environment variables or a secrets manager, and avoid printing your key in logs.
```python theme={null}
openai.api_key = os.environ.get("OPENAI_API_KEY")
```
## The browsing-and-summarizing function
Below is a complete asynchronous function you can place in a single Jupyter cell. It:
* launches a headless Chromium browser with Playwright,
* sets a custom user-agent and viewport,
* navigates to a URL and waits for DOMContentLoaded,
* captures and displays a full-page screenshot in the notebook,
* scrapes the first three paragraph elements from the Wikipedia content block (`#mw-content-text p`),
* sends the scraped text to GPT-4 for summarization,
* prints the extracted snippet and the GPT-4 summary.
Place the whole function in one cell and run it.
```python theme={null}
async def browse_and_display_then_summarize(user_agent: str, url: str, viewport: dict):
"""
Launch Playwright Chromium, visit `url` with provided `user_agent` and `viewport`,
take a screenshot, scrape the first three paragraphs under #mw-content-text,
and generate a GPT-4 summary of the scraped text.
"""
from playwright.async_api import async_playwright
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
context = await browser.new_context(
user_agent=user_agent,
viewport=viewport,
)
page = await context.new_page()
await page.goto(url, wait_until="domcontentloaded")
# Capture and display screenshot in the notebook
screenshot_bytes = await page.screenshot(type="png", full_page=True)
display(Image(data=screenshot_bytes))
# Scrape the first three paragraph elements from Wikipedia content
paragraphs = await page.query_selector_all("#mw-content-text p")
text_content = ""
for tag in paragraphs[:3]:
text = await tag.inner_text()
text_content += text.strip() + "\n\n"
# Close resources
await context.close()
await browser.close()
# Print a snippet of the extracted text for verification
print("\nExtracted Wikipedia Text (first 800 chars):\n")
print(text_content[:800] + ("..." if len(text_content) > 800 else "") + "\n")
# Ask GPT-4 to summarize the scraped text
print("\nGPT-4 Summary:\n")
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a helpful assistant. Summarize the given Wikipedia text in plain English."},
{"role": "user", "content": text_content},
],
temperature=0.5,
)
# Extract and print the model's summary
summary_text = response["choices"][0]["message"]["content"]
print(summary_text)
return summary_text
```
## Example: user agent, viewport, and running the agent
Create a user-agent string that simulates an iPhone-like browser and a viewport dictionary that mimics an iPhone 12 resolution. Then run the asynchronous function with `asyncio.run`.
```python theme={null}
# Example iPhone-style user agent string and viewport
iphone_user_agent = (
"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) "
"AppleWebKit/605.1.15 (KHTML, like Gecko) "
"Version/15.0 Mobile/15E148 Safari/604.1"
)
viewport = {"width": 375, "height": 812}
# Example URL: OpenAI Wikipedia page
url = "https://en.wikipedia.org/wiki/OpenAI"
# Run the async agent
asyncio.run(browse_and_display_then_summarize(iphone_user_agent, url, viewport))
```
When executed, the notebook will show the rendered page screenshot (using the supplied user agent and viewport), print the first portion of the scraped Wikipedia text, and print the GPT-4–generated summary.
From this base you can extend the agent to:
* scrape and aggregate content from multiple pages,
* index or store extracted highlights,
* generate study aids, flashcards, or quizzes automatically,
* add navigation logic to follow links, handle pagination, or respect robots.txt.
## Links and references
* Playwright Documentation: [https://playwright.dev/](https://playwright.dev/)
* OpenAI API Keys guide: [https://platform.openai.com/docs/guides/api-keys](https://platform.openai.com/docs/guides/api-keys)
* Python dotenv: [https://pypi.org/project/python-dotenv/](https://pypi.org/project/python-dotenv/)
Thank you for reading.
# Demo Searching Resumes for Keywords
Source: https://notes.kodekloud.com/docs/AI-Agents/Practical-Projects/Demo-Searching-Resumes-for-Keywords/page
Guide to building a Python agent that extracts keywords from job descriptions using OpenAI and scans PDF resumes for matches, reporting filenames, lines, keywords, and pages.
Welcome back.
In this guide we'll build a smart resume-screener agent in Python that:
* Extracts the most relevant keywords from a job description using an OpenAI GPT model,
* Scans all PDF resumes in a folder for those keywords, and
* Reports which resumes mention those keywords (including file name, matched keyword, matching line, and page number).
This workflow is useful for recruiters, hiring managers, and automated HR screening pipelines. Below is a cleaned, consolidated, and better-organized version of the code with step-by-step explanation.
Before running the code, install PyMuPDF (fitz) and any other dependencies you need. For example:
```bash theme={null}
pip install pymupdf python-dotenv openai
```
See the packages: [PyMuPDF](https://pypi.org/project/PyMuPDF/), [python-dotenv](https://pypi.org/project/python-dotenv/), and the [OpenAI Python client](https://github.com/openai/openai-python). Also set your OpenAI API key in an environment variable (for example, in a `.env` file): `OPENAI_API_KEY=your_key_here`. See OpenAI's API key docs: [https://platform.openai.com/docs/api-keys](https://platform.openai.com/docs/api-keys).
Dependencies at a glance:
| Package | Purpose | Install |
| -------------------- | --------------------------------------------- | --------------------------- |
| PyMuPDF (`fitz`) | Read and extract text from PDF files | `pip install pymupdf` |
| python-dotenv | Load environment variables from a `.env` file | `pip install python-dotenv` |
| OpenAI Python client | Call OpenAI APIs for keyword extraction | `pip install openai` |
## 1) Load environment variables and imports
Start by loading environment variables and importing required modules. This section sets up dotenv and common utilities.
```python theme={null}
from dotenv import load_dotenv
import os
import re
import asyncio
from pathlib import Path
load_dotenv() # Loads environment variables from .env into os.environ
```
Then import the agent and OpenAI client libraries and PyMuPDF. These imports provide the agent runtime, the OpenAI client, and PDF parsing.
```python theme={null}
from agents import Agent, Runner, ModelSettings
from agents.tool import function_tool
from openai import OpenAI
import fitz # PyMuPDF
```
Create the OpenAI client and set the directory that contains your resumes. Replace the path with your local folder of PDFs:
```python theme={null}
client = OpenAI()
RESUME_DIR = Path("/Users/your_user/Path/To/Resumes") # <-- change this to your folder
```
Security tip: Keep your `OPENAI_API_KEY` and any other secrets out of your repository (use `.env` or your platform's secret manager).
## 2) Define the PDF resume scanning tool
We expose a tool the agent can call: it opens each PDF in the folder, iterates pages and lines, and records matches for any of the provided keywords.
```python theme={null}
@function_tool(name_override="scan_resumes_for_keywords")
def scan_resumes_for_keywords(keywords: list[str]) -> list[dict]:
"""
Scans all PDF files in RESUME_DIR for occurrences of any keyword in `keywords`.
Returns a list of dicts with keys: filename, keyword, line, page.
"""
results: list[dict] = []
# Lower-case keywords for case-insensitive matching
lowered_keywords = [kw.lower() for kw in keywords]
for file in RESUME_DIR.glob("*.pdf"):
try:
doc = fitz.open(file)
except Exception as e:
# If a PDF cannot be opened, skip it (could log the error)
continue
for page in doc:
text = page.get_text() or ""
lines = text.splitlines()
for line in lines:
line_lower = line.lower()
for kw in lowered_keywords:
if kw and kw in line_lower:
results.append({
"filename": file.name,
"keyword": kw,
"line": line.strip(),
"page": page.number + 1
})
doc.close()
return results
```
Notes:
* Only `*.pdf` files are scanned.
* Matching is case-insensitive and performed per line. This keeps context (the line and page) for every hit.
* Each result contains `filename`, `keyword`, `line`, and a 1-based `page` number.
## 3) Extract keywords from a job description using OpenAI
Define a function that calls the OpenAI chat completion endpoint to extract a list of the most important skills/technologies from the job description. The function normalizes and cleans numbered or bulleted lists returned by the model.
```python theme={null}
def extract_keywords_from_job_description(job_text: str, n_keywords: int = 15) -> list[str]:
"""
Uses the OpenAI chat completions API (https://platform.openai.com/docs/guides/chat) to extract important skills/keywords
from the provided job_text. Returns up to n_keywords items.
"""
system_msg = (
"You are a job recruiter. Extract the 10–15 most important skills, "
"technologies, and keywords from the job description. Output them as a "
"simple list (one per line or comma-separated)."
)
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": system_msg},
{"role": "user", "content": job_text}
],
temperature=0.3
)
# Parse raw content and clean list items
raw_output = response.choices[0].message.content or ""
keywords: list[str] = []
for line in raw_output.splitlines():
# remove bullet/number prefixes like "1.", "-", "*", "•", "2)"
cleaned = re.sub(r'^[\s\-\*\.\d\)\•]+', '', line).strip()
if cleaned:
# If the line contains multiple comma-separated items, split them too
if "," in cleaned and len(cleaned.split(",")) > 1:
for part in cleaned.split(","):
part_clean = part.strip()
if part_clean:
keywords.append(part_clean)
else:
keywords.append(cleaned)
# Fallback: if the model returned a single-line comma-separated output
if not keywords:
for part in raw_output.split(","):
part_clean = part.strip()
if part_clean:
keywords.append(part_clean)
return keywords[:n_keywords]
```
Tips:
* Keep `temperature` low (e.g., 0.2–0.4) to improve determinism for extraction tasks.
* Consider adjusting the system prompt to include domain-specific terms or required exclusions.
## 4) Job description and running the agent
Use a job description (replace with one from your interface or user input), extract keywords, then create the agent and run the scan.
```python theme={null}
JOB_DESCRIPTION = """We're looking for a data scientist with experience in Python, machine learning,
data visualization, working with large datasets, SQL, version control (Git), and production deployment.
Experience with NumPy, pandas, and deploying models to cloud platforms is a plus."""
# Extract keywords from the job description
extracted_keywords = extract_keywords_from_job_description(JOB_DESCRIPTION)
print("\nExtracted Keywords:\n", extracted_keywords)
```
Create the agent and run it. The agent uses the `scan_resumes_for_keywords` tool defined earlier.
```python theme={null}
agent = Agent(
name="Resume Matcher",
instructions=(
"You are a resume scanner. The user will give you a job description. "
"First extract the keywords, then use the tool `scan_resumes_for_keywords` "
"to scan the resumes and report which resumes mention which keywords "
"(include filename, matched keyword, matching line, and page number)."
),
tools=[scan_resumes_for_keywords],
model="gpt-4",
model_settings=ModelSettings(truncation="auto"),
)
prompt = (
f"Scan the resumes for keywords that match this posting:\n\n{JOB_DESCRIPTION}\n\n"
f"The extracted keywords are: {', '.join(extracted_keywords)}"
)
# Run the agent using Runner. Runner.run is async, so use asyncio.run to execute it.
if __name__ == "__main__":
result = asyncio.run(Runner.run(agent, prompt))
print("\nResume Scan Results:\n")
print(result)
```
Operational notes:
* `Runner.run` is asynchronous; the `asyncio.run(...)` wrapper is appropriate for simple scripts.
* For long-running or production use, integrate into an async event loop or background worker.
## 5) Example output
A sample (cleaned) output might look like:
```plaintext theme={null}
Resume Scan Results:
RunResult:
- Last agent: Agent(name="Resume Matcher", ...)
- Final output (str):
Here are the results of scanning the resumes for the extracted keywords:
### fake_resume_john_doe.pdf
- Python: Programming Languages: Python, Java, C++ (Page 1)
- Python: Implemented scalable Python microservices for data ingestion pipelines (Page 1)
- Machine Learning: Designed and deployed ML models to improve recommendations (Page 1)
- Git: Tools: Git, Docker, Kubernetes (Page 1)
### resume_1.pdf
- Python: Python, JavaScript, React, Node.js, Docker (Page 1)
### resume_2.pdf
- Python: Python, R, Machine Learning, TensorFlow, SQL (Page 1)
- SQL: Experience with SQL for analytics and pipelines (Page 2)
### resume_3.pdf
- AWS: AWS, Docker, Kubernetes, CI/CD (Page 1)
The identified resumes contain keywords related to Python, Machine Learning, Git, SQL, and cloud tooling.
```
## Next steps / improvements
* Rank resumes by the number of matched keywords or weighted importance.
* Export results to CSV, JSON, or store in a database for later analysis.
* Add a web UI or email summary for recruiters.
* Improve keyword extraction with domain-specific prompts, stop-words, or normalization (e.g., treat "ML" and "Machine Learning" as synonyms).
* Add fuzzy matching or synonym expansion using libraries like `fuzzywuzzy`/`rapidfuzz` or embedding similarity.
## Links and references
* OpenAI Chat Completions guide: [https://platform.openai.com/docs/guides/chat](https://platform.openai.com/docs/guides/chat)
* OpenAI API keys: [https://platform.openai.com/docs/api-keys](https://platform.openai.com/docs/api-keys)
* PyMuPDF documentation: [https://pymupdf.readthedocs.io/](https://pymupdf.readthedocs.io/)
* python-dotenv: [https://pypi.org/project/python-dotenv/](https://pypi.org/project/python-dotenv/)
* OpenAI Python client: [https://github.com/openai/openai-python](https://github.com/openai/openai-python)
You now have a working agent-based resume screener that extracts relevant keywords from a job posting and scans PDF resumes for those keywords. Adjust the prompt, keyword limits, and matching logic to fit your organization's hiring criteria.
# Task Automation in AI Agents
Source: https://notes.kodekloud.com/docs/AI-Agents/Practical-Projects/Task-Automation-in-AI-Agents/page
Overview of task automation for AI agents covering planning, tool integration, memory, workflows, triggers, and best practices for building reliable autonomous task-executing systems
Welcome back. In this lesson we explore task automation for AI agents: how agents move from conversation to autonomous action. You’ll learn why automation matters, how agents plan and execute tasks, what tools and architectures enable reliable workflows, and practical patterns for production systems.
What we cover
* Task automation fundamentals for AI agents
* Benefits and challenges
* Types of tasks and integrations
* The agent–task loop (Observe → Design/Plan → Act)
* Task decomposition and planning
* Tools, APIs, and environment integration
* Memory and context management
* Automation patterns, triggers, and schedulers
* Real-world use cases
* Best practices for safe, observable automation
Task automation turns agents into autonomous workers that take input, reason, plan, and act — for example: processing files, scheduling actions, calling APIs, or generating reports. Core enabling capabilities include planning, tool use, memory, and reliability mechanisms. When done well, automated agents function as digital collaborators that reliably execute repeatable tasks at scale.
How a modern AI agent functions
This diagram shows a modern AI agent acting as a central intelligence hub. The flow starts with a user prompt; the agent interprets intent, generates a task list, and executes actions. It interacts with data sources, a code executor, specialized models, and LLMs, then returns outputs to the user.
Key integratable components
* Data: Query SQL, search indexes, or structured/unstructured sources.
* Code executor: Run generated code in sandboxed environments and return execution results.
* Specialized ML models: Forecasting, optimization, or domain-specific inference.
* LLMs: Planning, summarization, and complex natural language understanding (e.g., GPT-style or LLaMA-family models).
Benefits and trade-offs
Task automation delivers clear advantages:
* Reduced human workload for repetitive tasks
* Consistent, accurate execution of instructions
* Continuous operation and scaling across time zones
But automation also introduces challenges:
* Handling edge cases and ambiguous inputs
* Maintaining traceability, auditability, and reliability
* Managing compute costs and resource usage as systems scale
Types of tasks apt for automation
Below are common categories that map to typical agent capabilities.
| Task Category | Typical Actions | Example integrations |
| ----------------------- | ------------------------------------------------ | ----------------------------------- |
| Data operations | Parsing, transform, cleaning, summarization | `SQL`, Elasticsearch, cloud storage |
| Workflow tasks | Email, file moves, DB updates, spreadsheet edits | Email APIs, Google Drive, Notion |
| Scheduling & monitoring | Reminders, threshold alerts, periodic checks | Cron, cloud schedulers, task queues |
| Advanced autonomy | Research, code generation, testing | LLMs + sandboxed executors |
| API & RPA | Enterprise workflows and low-code automations | Slack, Jira, RPA platforms |
You can automate across tools like [Notion](https://www.notion.so/), [Slack](https://slack.com/), [Google Drive](https://drive.google.com/), and [Jira](https://www.atlassian.com/software/jira).
The agent–task loop
Every automation agent typically follows a closed loop:
1. Observe — receive input or perceive environment events (webhooks, file changes, user prompts).
2. Design / Plan — determine a sequence of steps or a task tree (static or LLM-driven).
3. Act — invoke tools, call APIs, run code, or produce artifacts.
4. (Optional) Reflect / Store — update memory, emit logs, and persist results for future decisions.
This loop supports iterative improvement, recovery from failures, and stateful behavior across steps.
Task decomposition and planning
Large tasks are decomposed into smaller, testable subtasks. Example: “send a daily summary” decomposes to:
* Fetch the latest data
* Summarize key insights
* Format the message
* Send email or post to a channel
Decomposition enables stepwise execution, clearer tool responsibilities, retry strategies, and easier observability. Planning strategies:
* Static plans — predefined step lists for deterministic flows
* Dynamic plans — LLM or planner-generated task trees that adapt to context
Tools, APIs, and environment integration
Agents act through integrable tools and execution environments:
* REST APIs, RPCs, and SDKs
* Python functions and serverless sandboxes
* Shell commands and containerized runtimes
* Cloud services (storage, pub/sub, schedulers)
Frameworks such as [LangChain](https://learn.kodekloud.com/user/courses/langchain) and other agent frameworks abstract tools into callable primitives. Examples:
* Use the `Google Drive API` to fetch a spreadsheet
* Run a summarization model to condense content
* Call an email API to send results
This modular, tool-centric pattern ensures extensibility and safer execution boundaries.
Memory and context for reliable automation
Memory enables continuity and personalization:
* Short-term memory: session state, which step the agent is on
* Long-term memory: persisted preferences, processed documents, or user history
Memory reduces redundant work and supports adaptive behavior. Without memory, flows are stateless and repeat work on each trigger.
Architectural patterns
Choose a pattern depending on complexity, scale, and fault tolerance:
| Pattern | When to use | Characteristics |
| ---------------------- | --------------------------------------------------- | ------------------------------------------------- |
| Single-agent loop | Simple tasks (file renames, basic notifications) | Easier to implement; single point of control |
| Multi-agent pipeline | Complex workflows (research → summarize → validate) | Specialized workers, better fault isolation |
| Event-triggered agents | Real-time reactions (webhooks, file uploads) | Low latency, reactive |
| Scheduled agents | Periodic reports or maintenance | Cron-like cadence using schedulers or task queues |
Triggers and schedulers
Triggers (event-driven) and schedulers (time-driven) start automated flows:
* Triggers: incoming HTTP requests, webhook events, file-system watchers, messages
* Schedulers: cron jobs, cloud schedulers, or libraries like `Celery` for periodic tasks
Use event triggers for real-time workflows and schedulers for routine, time-based tasks.
Common production use cases
* Downloads Folder Organizer: monitor a folder to categorize, rename, and move files.
* Email Responder: classify incoming mail, draft replies, and escalate to humans when needed.
* GitHub PR Triage: review new PRs, assign reviewers, and add labels.
* Slack Daily Summarizer: aggregate unread messages into an end-of-day brief.
These patterns reduce cognitive load and speed up team workflows.
Best practices for safe, observable automation
* Validate inputs before acting; ambiguous or malformed inputs should trigger clarification.
* Apply structured error handling, backoff, and retry logic to tolerate transient failures.
* Modularize components (parsing, summarizing, emailing) to limit blast radius on failures.
* Log actions, errors, and metrics for observability and troubleshooting.
* Use role separation: give each agent a clear, singular responsibility and defined interfaces.
* Enforce access controls and least privilege when calling external services.
Validate inputs, isolate tools, and log actions. These steps greatly reduce the risk of unexpected behavior and make debugging simpler.
Conclusion
By combining clear task decomposition, robust tool integration, contextual memory, and strong observability, you can design AI agents that safely automate meaningful work. For production-grade automation, prioritize input validation, modularity, and monitoring before optimizing for cost and scale.
Links and references
* [Kubernetes Basics](https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/)
* [LangChain](https://learn.kodekloud.com/user/courses/langchain)
* [Google Drive API](https://developers.google.com/drive/api)
* [Celery documentation](https://docs.celeryq.dev/en/stable/)
# Understanding Agent Computer Tools
Source: https://notes.kodekloud.com/docs/AI-Agents/Practical-Projects/Understanding-Agent-Computer-Tools/page
Guide to using Playwright browser automation for AI agents, covering integration patterns, capabilities, use cases, architecture, security, and production best practices.
Welcome back.
In this lesson we begin exploring agent-computer tools with a focus on Playwright — a modern browser automation framework well suited to AI agents. This guide covers what agent-computer tools are, why browser automation matters for agents, Playwright’s core capabilities, integration patterns, practical use cases, architecture and runtime flow, security considerations, and best practices for production.
Topics covered:
* Agent-computer tools: what they are and why they matter
* Why browser automation is important for agents
* Understanding Playwright and its core capabilities
* Integrating Playwright with AI agents (pattern and example)
* Use cases for web scraping and data extraction
* Typical architecture and runtime flow
* Security, sandboxing, and practical limitations
* Comparing Playwright to other browser automation tools
* Best practices and real-world examples
Agent-computer tools let AI agents move beyond purely language-based tasks into real-world actions inside digital environments. Examples include browser control, file handling, terminal commands, and operating system automation. When agents have these capabilities they can simulate human interactions — navigating websites, completing forms, downloading files, or operating software UIs — turning plans into executed workflows and enabling end-to-end automation.
What are agent-computer tools and when to use them
Agent-computer tools are external interfaces or services that allow an agent to act, not just reason. These tools are essential when:
* No API exists or an API is restricted or rate-limited.
* The workflow requires simulating human interaction (multi-step logins, consent dialogs).
* Client-side JavaScript or dynamic rendering prevents simple HTTP scraping.
Browser automation tools, such as Playwright, are a common agent-computer tool because they allow programmatic control of a full browser context: navigating pages, clicking, typing, uploading/downloading files, and extracting rendered content.
Why browser automation is often necessary
Browser automation becomes necessary in many realistic scenarios:
* Public APIs are absent, restricted, or require partner agreements.
* Workflows require a real user session (multi-step flows, SSO, consent screens).
* Pages rely on client-side frameworks (React, Vue, Angular) that render content dynamically.
Example: an agent must log into a claim portal, navigate to a specific case, and summarize the status. Without a browser context the agent can reason about instructions but cannot interact with the portal; with browser automation it can perform the necessary actions and return results.
Playwright overview
Playwright is an open-source browser automation framework from Microsoft that supports Chromium, Firefox, and WebKit. It provides robust primitives for automated interactions:
* Page navigation, clicks, typing, and file uploads/downloads
* Pop-up and multi-page handling
* Network interception and request/response inspection
* Screenshots, PDFs, and visual evidence capture
* Auto-waiting for elements and reliable async handling
These features make Playwright well-suited for agent integration: agents can locate elements with selectors, simulate user input, monitor network traffic, and capture visual proof for reporting or auditing.
Integrating Playwright with AI agents
A common integration pattern is to wrap Playwright actions inside tool functions or expose them via a microservice API that the agent can call. The agent issues a structured plan (for example: go to site → login → navigate to dashboard → extract balance). Each step maps to a Playwright routine, and results are returned to the agent so it can continue reasoning or take further actions.
Example (Python, synchronous Playwright API) — focused login-and-extract flow:
```python theme={null}
from playwright.sync_api import sync_playwright
def fetch_balance(url: str, username: str, password: str) -> str:
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto(url, wait_until="networkidle")
page.fill('input#username', username)
page.fill('input#password', password)
page.click('button[type="submit"]')
page.wait_for_selector('#balance', timeout=10000)
balance = page.inner_text('#balance')
browser.close()
return balance
```
In agent frameworks (for example, a LangChain-style tool wrapper or a function-calling workflow with a large language model), the agent calls functions like `fetch_balance`, receives structured results, and decides whether to finish or issue additional steps. This read-act-think-act loop enables mid-execution adjustments and robust error handling.
Common use cases
* Research agents: extract citations and metadata from academic sites
* Customer support: log into internal dashboards and fetch user status
* Autonomous QA: run nightly flows to detect regressions or UI breakages
* Data scraping: collect product listings, pricing, and availability from web UIs
* Workflow automation: submit forms, pull invoices, or interact with legacy portals lacking APIs
Architecture and runtime flow
A typical agent + Playwright architecture follows these steps:
1. A user prompt or scheduled trigger initiates the task.
2. The AI agent interprets the goal and decomposes it into discrete steps.
3. Steps are dispatched to a Playwright tool wrapper (local process or microservice).
4. The wrapper launches a browser context, performs actions, and gathers results (text, screenshots, network logs).
5. Results are returned to the agent for further reasoning or final output.
This cycle mirrors human workflows: observe, act, reflect, and act again.
Security, sandboxing, and limitations
Browser automation is powerful but comes with practical and security constraints:
* Sites may detect and throttle automated browsers (bot detection, CAPTCHAs).
* Multi-factor authentication and advanced anti-bot defenses can block automation.
* Unconstrained agents risk performing unsafe actions (clicking harmful links or exfiltrating data).
Mitigations:
* Enforce domain allow lists, rate limits, and click limits.
* Run agents inside isolated sandboxes with constrained network access.
* Record and log every browser action for auditing and debugging.
* Use per-session credentials and avoid storing sensitive secrets in-process.
* Implement human approval for sensitive or irreversible actions.
Automated interaction with third-party sites can have legal or terms-of-service implications. Always confirm that scraping or automation is permitted, and avoid actions that could impersonate or harm users.
Comparisons and practical advice
Playwright compares favorably to other browser automation tools depending on requirements:
| Tool | Strengths | Trade-offs |
| ------------------------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| [Playwright](https://playwright.dev/) | Cross-browser (Chromium, Firefox, WebKit), auto-waits, modern async APIs, reliable for dynamic pages | Slightly newer ecosystem, learning curve for advanced features |
| [Selenium](https://www.selenium.dev/) | Mature, broad language support, large ecosystem | Can be slower and more brittle with modern dynamic UIs |
| [Puppeteer](https://pptr.dev/) | Fast and stable for Chromium | Chromium-only (limited cross-browser support) |
Practical advice for robust automation:
* Prefer stable selectors (IDs, `data-*` attributes) over fragile XPaths.
* Use explicit waits (e.g., `wait_for_selector`, `wait_until="networkidle"`) for dynamic content.
* Modularize functionality into small, testable functions or endpoints the agent can call.
* Wrap actions in try/except (or try/catch) and return structured errors the agent can handle.
* Log actions and responses with timestamps for traceability.
* Never inject unvalidated user input directly into navigations or selectors.
Design agent workflows so Playwright calls are idempotent and have clear failure modes; this simplifies retries and recovery.
Real-world examples
* Recruitment automation: an agent logs into LinkedIn Recruiter, searches for candidates that match criteria, extracts profiles, and drafts outreach messages.
* Continuous QA: an automated tester navigates critical purchase flows daily, captures screenshots for failures, and opens tickets with logs.
* Healthcare portals: an automation agent logs into patient portals to download statements, reconcile invoices, and flag discrepancies for human review.
Playwright empowers agents to act where APIs are unavailable, converting high-level plans into executed tasks. With careful architecture, sandboxing, observability, and legal compliance, Playwright-based agent tools can safely extend an agent’s capabilities into real-world systems.
# Understanding FireSearchTool
Source: https://notes.kodekloud.com/docs/AI-Agents/Practical-Projects/Understanding-FireSearchTool/page
Explains FileSearchTool, a session-scoped semantic file search in OpenAI Agents for chunking, embedding, retrieval, use cases, architecture, best practices, and comparisons to external vector databases.
Welcome back.
In this lesson we’ll explore the FileSearchTool: what it is, why file-based semantic search matters for AI agents, how the tool is architected, how it compares to external vector databases, and practical guidance for using it securely and at scale. We cover indexing, chunking, query flow, typical use cases, best practices, and future directions.
## Overview
The FileSearchTool enables agents to semantically search and interact with file contents so static documents become active knowledge sources. This is essential when agents must summarize, extract, validate, or reason over contracts, reports, datasets, policies, or other large documents.
Unlike a developer-managed embedding pipeline paired with an external vector database, the FileSearchTool is a native component of the OpenAI Agents SDK that handles chunking, embedding, and retrieval with minimal setup. It helps agents scale beyond prompt size limits and return grounded answers that cite source passages — a requirement for high-trust workflows such as compliance checks, legal review, and data analysis.
## What FileSearchTool Does
FileSearchTool provides native, session-scoped access to file-based knowledge for agents:
* Breaks documents into semantically coherent chunks (paragraphs, sections, or sliding windows with overlap).
* Generates vector embeddings for each chunk using OpenAI embedding models.
* Stores embeddings and metadata in a temporary vector index scoped to the agent session.
* Accepts natural-language queries, converts them to embeddings, and returns the most relevant chunks by similarity.
* Injects retrieved chunks into the agent prompt so the model can generate grounded, context-aware responses.
This pipeline delivers semantic retrieval that prioritizes meaning over keyword matches and supports PDFs, Word docs, plain text, logs, CSV/JSON, and other structured formats. It’s optimized for session-focused tasks like Q\&A, summarization, and on-the-fly compliance checks.
## Why file-based semantic search matters
Large documents rarely fit fully in an LLM’s context window. Agents therefore need a fast, accurate way to locate the most relevant passages and feed only that context to the model. FileSearchTool solves this by performing semantic search over document chunks so the agent receives the most informative context for a given query. This is particularly valuable in enterprise scenarios: contract analysis, policy review, auditing, and extracting findings from long research papers.
## Architecture and search flow
The FileSearchTool follows a clear pipeline optimized for speed and relevance:
* File upload: Upload files to the agent workspace (user or service).
* Chunking: Split files into manageable, semantically coherent chunks.
* Embedding: Convert each chunk to an embedding via an OpenAI embedding model.
* Indexing: Store embeddings plus metadata (file name, chunk offsets, titles) in a session-scoped vector index.
* Querying: Embed incoming natural-language queries and run a vector-similarity search to return top chunks.
* Context injection: Insert retrieved chunks into the agent prompt to produce a grounded response.
This design keeps LLM inputs within token limits while delivering context-rich retrieval.
## Usage pattern
Integrating FileSearchTool into an OpenAI agent is straightforward: register the tool, upload files, and let the agent query the indexed content using natural language. The tool abstracts chunking, embedding, and retrieval so developers can focus on agent prompts, behavior, and business logic.
Example pseudocode (illustrative):
```python theme={null}
# python
# Example usage pattern for an agent with FileSearchTool
from openai import OpenAI
from openai.agents import Agent, FileSearchTool
client = OpenAI()
agent = Agent(tools=[FileSearchTool()])
# Upload files into the agent's workspace (session-scoped)
agent.tools["file_search"].upload_file("contracts/nda.pdf")
agent.tools["file_search"].upload_file("reports/strategy_2026.pdf")
# Query using natural language; the tool performs retrieval internally
response = agent.run("What are the key deliverables mentioned in the NDA?")
print(response)
```
Common configuration knobs you’ll use include chunk size, overlap, `max_num_results` (limit retrieved chunks), and metadata filters to scope searches.
## Typical use cases
* Contract review agents: identify clauses, deadlines, or penalty terms.
* Compliance bots: cross-reference internal policies with regulations.
* Report assistants: extract key insights from long business or scientific documents.
* Data validation: verify CSV records, flag anomalies, or reconcile entries.
* Q\&A and knowledge assistants: deliver sourced answers from internal files.
## Security, storage, and performance considerations
FileSearchTool processes files inside the agent runtime. By default, the vector index is session-scoped and not persisted across sessions unless you explicitly export or save embeddings to external storage. Because indexing often occurs in-memory, handling many or very large files can increase memory and CPU usage and affect agent responsiveness.
Always treat sensitive files with strict controls: use role-based access, encryption at rest, session timeouts, memory limits, and logging. Monitor how long files persist in the agent workspace and ensure compliance with your organization's data handling policies.
## Comparing FileSearchTool to external vector databases
| Capability | FileSearchTool (native) | External Vector DBs |
| ---------------------- | -----------------------------------------------------------------------------: | --------------------------------------------------------------------------------------------------- |
| Setup complexity | Very low — built into the Agents SDK with minimal configuration | Medium–high — requires infrastructure, auth, and index management (e.g., Pinecone, FAISS, Weaviate) |
| Persistence | Session-scoped by default (temporary) | Persistent — suitable for multi-session, multi-user use cases |
| Integration effort | Minimal glue code; native API | Client libraries and synchronization logic required |
| Scale and access | Ideal for single-agent or single-session workflows and rapid prototyping | Designed for large-scale, multi-user, production search across millions of documents |
| Typical recommendation | Fast prototyping, scoped agent workflows, privacy-sensitive temporary sessions | Long-term knowledge bases, multi-user search, high-availability production systems |
References:
* Pinecone: [https://www.pinecone.io](https://www.pinecone.io)
* FAISS: [https://github.com/facebookresearch/faiss](https://github.com/facebookresearch/faiss)
* Weaviate: [https://weaviate.io](https://weaviate.io)
Recommendation: Use FileSearchTool for rapid prototyping and session-scoped agent tasks. For long-term persistence, high concurrency, or very large corpora, pair an embedding pipeline with a dedicated vector database.
## Best practices
* Preprocess and clean documents before upload — consistent structure and clear section headers improve chunking quality.
* Choose chunk sizes that preserve semantic coherence and respect token limits; small overlaps help avoid content loss at boundaries.
* Limit retrieved chunks (set `max_num_results`) to prevent context bloat and token overrun.
* Attach and index metadata (file titles, authors, timestamps) and use metadata filters to narrow results.
* Tag files for source, team, or domain filtering if you need scoped searches.
* Monitor memory and CPU usage during indexing and retrieval; batch or stream large files when possible.
Tip: Prefer semantic search over raw keyword matches to improve retrieval quality. Combine semantic ranking with metadata filters to return a smaller, highly relevant context set for the LLM.
## Limitations and future directions
Current constraints include session-scoped persistence and memory pressure for very large document collections. Potential future enhancements include:
* Hybrid keyword + semantic search for faster recall and pre-filtering.
* Streaming or incremental indexing for very large files.
* Dynamic re-indexing when files change and real-time triggers.
* Optional connectors to persistent vector backends for long-lived knowledge stores.
* Improved tooling for chunking configuration, overlap control, and metadata management.
## Conclusion
File-based retrieval is a core capability for agent workflows that must reason over large or structured documents. The FileSearchTool provides an easy-to-use, session-scoped semantic search experience optimized for agent contexts — ideal for rapid prototyping and single-session tasks. For production-grade, persistent, multi-user systems or massive scale, augment FileSearchTool with a persistent vector database and a strong data governance model.
This lesson covered FileSearchTool’s design, pipeline, best practices, and tradeoffs to help you decide when to use it and how to integrate it effectively.
## Links and references
* OpenAI Agents SDK docs: [https://platform.openai.com/docs/agents](https://platform.openai.com/docs/agents)
* Pinecone: [https://www.pinecone.io](https://www.pinecone.io)
* FAISS: [https://github.com/facebookresearch/faiss](https://github.com/facebookresearch/faiss)
* Weaviate: [https://weaviate.io](https://weaviate.io)
# AI Agents Introduction
Source: https://notes.kodekloud.com/docs/AI-Agents/Prerequisites/AI-Agents-Introduction/page
Overview of AI agents including definition, architecture, capabilities, differences from traditional AI and applications
In this lesson we introduce AI agents: what they are, how they differ from traditional AI, their internal anatomy, core capabilities, real-world applications, the historical evolution of agentic systems, and why they matter today.
Understanding AI agents is fundamental to building intelligent systems that can reason, plan, and act autonomously. These agents power digital assistants, research companions, scheduling tools, and many other applications. Unlike one-off predictive models or rigid rule-based programs, agents are goal-driven systems that use memory, tools, and multi-step reasoning to solve complex, changing problems.
## What is an AI agent?
An AI agent is a system that perceives its environment, reasons about observations, and takes actions to achieve defined goals — often autonomously. Agents can call APIs, browse the web, manipulate files, trigger other systems, and interact with people to complete multi-step tasks.
An AI agent follows a human-like problem-solving cycle: observe, decide, act. It combines goals, prior knowledge, and capabilities to produce autonomous, goal-directed behavior.
Agents operate in a feedback loop: they sense inputs, plan using their internal knowledge and tools, act on the environment, and update their state (short-term or long-term memory) based on outcomes. Over time, this loop enables adaptation and continual improvement.
## How AI agents differ from traditional AI
Traditional AI systems are typically reactive: provide an input and receive an output (for example, a classification or a computed result). AI agents are proactive: they can initiate work, decompose tasks, track progress, recover from failures, and take independent multi-step actions.
* Traditional AI: stateless, prompt-and-response, one-step outputs.
* AI agents: stateful, goal-driven, multi-step workflows, tool-enabled.
## Core components of an AI agent
A typical agent architecture includes modular components that together enable perception, reasoning, planning, action, and learning.
| Component | Purpose | Examples |
| -------------------- | --------------------------------------------------- | ------------------------------------------------------- |
| Perception System | Interpret inputs from users, sensors, or files | Natural language parsing, OCR, audio transcription |
| Reasoning & Planning | Generate plans, decompose tasks, and make decisions | LLM prompts, logic engines, search-based planners |
| Memory | Store short-term context and long-term knowledge | Conversation context, user preferences, knowledge bases |
| Effectors / Tools | Execute actions in the environment | Calendars, APIs, code interpreters, web browsers |
These modules form feedback loops that let the agent re-evaluate results, adjust planning, and iterate until the goal is satisfied or a defined failure state is reached.
## How an agent thinks and acts (anatomy in practice)
At the center of the system is the reasoning engine — often a Large Language Model (LLM) — which interprets goals, generates plans, and issues commands to tools. Planning typically involves sub-goal decomposition, self-reflection, and critique loops; execution involves calling tools and updating memory.
The diagram below expands this into a broader ecosystem: role definitions, interfaces, tool integrations, logging, audits, and human supervision all interact with the LLM to produce auditable, safe outcomes.
AI agents interacting with external systems require robust guardrails: access control, logging, audit trails, and human-in-the-loop review to maintain safety, compliance, and traceability.
## Modern AI agent capabilities
Modern agents go beyond language understanding to interact with tools, maintain goals over time, and connect to live data sources. Key capabilities:
| Capability | What it enables | Examples |
| --------------------------------- | ----------------------------------------- | --------------------------------------------------- |
| Natural language understanding | Interpret complex instructions and intent | Conversational reasoning, instruction parsing |
| Tool use & action-taking | Perform operations in external systems | API calls, database queries, code execution |
| Goal tracking & adaptive planning | Break down tasks and replan on failures | Subtask decomposition, progress monitoring |
| External connectivity | Access live data and documents | Reading PDFs, querying APIs, browsing web resources |
| Collaboration | Work with humans or other agents | Shared task handoff, multi-agent orchestration |
These capabilities enable agents to evolve from chatbots into digital workers that solve real problems and automate workflows.
## Real-world use cases
Agents are already deployed across many industries. Representative use cases:
| Industry / Role | Agent tasks |
| ----------------------- | ----------------------------------------------------------------- |
| Executive assistant | Manage calendars, summarize emails, schedule meetings |
| Finance advisor | Monitor markets, analyze news, generate investment insights |
| Education | Personalized tutoring, adaptive practice exercises |
| Task automation | Automate email responses, workflow orchestration, code deployment |
| Multimodal applications | Combine vision, speech, and sensors in smart devices |
| Research assistant | Web search, literature summarization, knowledge synthesis |
Agents often integrate with services like Google Calendar, Notion, Slack, and cloud APIs to perform context-aware automation.
## Evolution of AI agents
Agent architectures have progressed from simple, rule-based systems to sophisticated, learning-enabled agents:
* If-then rule systems: predictable but brittle in dynamic environments.
* Model-based agents: internal world models for better context handling.
* Goal-based & utility-based agents: planning and outcome evaluation.
* Learning agents: adapt via experience and data-driven policies.
* Modern agents: multi-step reasoning, tool use, and autonomous initiation.
This evolution enables agents that can reason across steps, call tools as needed, and improve performance through feedback.
## Why AI agents matter
AI agents unite decision-making, learning, and autonomous action. They reduce human cognitive load, automate complex workflows, and scale intelligent assistance across domains such as business, healthcare, and research. When combined with robust controls and human oversight, agents become indispensable collaborators rather than simple task executors.
As agents continue to integrate with tools, live data, and human workflows, they will play a central role in building autonomous, auditable, and efficient systems that augment human capabilities.
## Links and references
* [Large language model (LLM) — Wikipedia](https://en.wikipedia.org/wiki/Large_language_model)
* [Autonomous agent — Wikipedia](https://en.wikipedia.org/wiki/Autonomous_agent)
* For best practices on safe agent deployment, consult provider documentation and industry guidelines on auditability, access control, and human oversight.
# AI Development Key Concepts
Source: https://notes.kodekloud.com/docs/AI-Agents/Prerequisites/AI-Development-Key-Concepts/page
Foundational guide to AI and machine learning for building adaptive agents, explaining learning paradigms, Sense Think Act capabilities, and feedback loops for continuous improvement
In this lesson we cover the foundational concepts for building and operating AI agents. You’ll learn how AI and machine learning enable agent behavior, the principal learning paradigms, the agent Sense–Think–Act capabilities, and how feedback loops drive continuous improvement. Mastering these concepts helps you design agents that are adaptive, reliable, and aligned with real-world goals.
We’ll review:
* What artificial intelligence enables for agents
* The role of machine learning and its learning paradigms
* Core agent capabilities: perception, reasoning/planning, and action
* Feedback loops and continuous improvement for deployed agents
## What is Artificial Intelligence for Agents?
Artificial intelligence (AI) describes systems that perform tasks requiring human-like cognitive functions — learning, reasoning, problem-solving, and decision-making. For agents, AI provides the mechanisms to:
* Sense the environment (user input, telemetry, logs, sensor streams)
* Process and interpret information (models, heuristics, LLMs)
* Decide and plan actions (policies, workflows)
* Act using available effectors (APIs, UI automation, actuators)
With AI, agents can operate autonomously, handle dynamic and uncertain environments, and respond to novel situations. Without AI, agent behavior tends to be static and rule-bound, limiting adaptability and long-term effectiveness.
## Machine Learning: The Engine of Adaptive Agents
Machine learning (ML) is the subset of AI that enables systems to improve from data and experience rather than explicit reprogramming. In agents, ML shifts behavior from fixed rules to adaptive policies: agents observe outcomes, update internal models, and refine actions over time.
Key ML applications for agents:
* Prediction (forecasting outcomes or next best actions)
* Classification (intent detection, anomaly detection)
* Optimization (policy tuning, resource allocation)
* Personalization (tailoring responses or recommendations based on user behavior)
ML allows support bots, recommendation engines, and automation agents to evolve as they encounter more data and feedback.
## Learning Paradigms for Agents
Agents typically rely on one or more of these learning paradigms. The choice depends on available data, the problem structure, and performance objectives.
| Paradigm | What it learns | Typical use cases | Examples / Algorithms |
| --------------------------- | ----------------------------------------------------------------------: | -------------------------------------------------------------- | ---------------------------------------------------- |
| Supervised learning | Maps inputs to labels or continuous targets | Classification (intent detection), regression (forecasting) | Logistic regression, neural networks, decision trees |
| Unsupervised learning | Discovers structure or patterns in unlabeled data | Clustering, anomaly detection, feature extraction | K-means, DBSCAN, PCA, autoencoders |
| Reinforcement learning (RL) | Learns policies by maximizing cumulative reward through trial and error | Sequential decision-making, robotics, game-playing, navigation | Q-learning, PPO, DQN, policy gradients |
Each paradigm enables different capabilities: supervised models are effective when labeled examples exist; unsupervised methods help discover latent structure; RL is suitable for goal-directed, sequential tasks where feedback can be expressed as reward.
### More detail on each paradigm
* Supervised learning
* Classification: diagnostics, fraud detection, image recognition.
* Regression: sales forecasting, price/risk estimation.
* Unsupervised learning
* Clustering: customer segmentation, exploratory analysis for recommender systems.
* Dimensionality reduction: visualization, noise reduction, feature engineering.
* Reinforcement learning
* Goal-oriented, sequential decision making: trading algorithms, robot navigation, skill acquisition through interaction and reward signals.
These paradigms are often combined—for example, supervised models for perception plus RL for high-level policy optimization.
## Core Agent Capabilities: Sense, Think, Act
A practical way to reason about agents is the Sense–Think–Act loop:
* Perception (Sense): Ingest and interpret signals — text, images, sensor telemetry, or structured logs. Techniques include NLP pipelines, vision models, and signal processing.
* Reasoning & Planning (Think): Decide what to do using internal state, learned models, or planning algorithms (e.g., search, LLM planning, RL policies).
* Action (Act): Execute tasks through APIs, automation scripts, UIs, or physical actuators. Actions change the environment and produce new percepts.
These capabilities form a continuous loop enabling adaptive behavior.
Remember: perception supplies context, reasoning selects the best action given that context, and action changes the environment — which then produces new percepts for the next cycle.
## Feedback Loops and Continuous Improvement
Learning from feedback is what enables agents to improve. Feedback can be immediate (error responses, failed API calls) or long-term (user satisfaction metrics, conversion rates). Agents that log outcomes and use those observations to update models become increasingly effective.
A typical continuous-improvement cycle:
1. Define a measurable goal (e.g., reduce mean time to resolution).
2. Observe current state and collect contextual data (logs, metrics, user signals).
3. Decide on an action or policy change.
4. Execute the action in production or a test environment.
5. Observe outcomes and compute feedback signals.
6. Update models, rules, or policies; repeat.
This iterative loop supports personalization, automation of routine tasks, and appropriate escalation to humans for complex cases.
## Putting the Concepts Together
In production, agents typically:
* Collect data from users, system logs, sensors, and operational telemetry.
* Use ML models and heuristics to detect patterns and make decisions.
* Execute actions (resolve tickets, recommend products, trigger workflows).
* Capture feedback to refine models, adjust thresholds, or revise policies.
This pipeline supports scalable automation, improved decision quality over time, and safe escalation paths to human operators for ambiguous or high-risk scenarios.
Further reading and references:
* [Machine Learning overview (Wikipedia)](https://en.wikipedia.org/wiki/Machine_learning)
* [Reinforcement Learning (overview)](https://en.wikipedia.org/wiki/Reinforcement_learning)
* [Designing agent architectures and feedback loops — best practices](/docs/agent-design)
# AI Technologies for Agents Overview
Source: https://notes.kodekloud.com/docs/AI-Agents/Prerequisites/AI-Technologies-for-Agents-Overview/page
Overview of AI technologies for building memory-enabled, tool-using agents, covering embeddings, vector databases, retrieval augmented generation, orchestration frameworks, and guidance for selecting production-ready stacks.
Welcome back.
In this lesson we provide a structured overview of the key AI technologies behind intelligent agents. You’ll learn what each component does, how they fit together, and practical guidance for choosing the right stack when building memory-enabled, tool-using agents.
Key topics covered:
* Embeddings and semantic representation
* Vector databases and providers
* Agent memory and retrieval patterns
* Traditional databases vs. vector databases
* Agent frameworks and tooling ecosystems
* Connecting embeddings, memory, and Retrieval-Augmented Generation (RAG)
* How to choose the right tech stack for your agent project
AI agents depend on a combination of embeddings, vector search, orchestration frameworks, and APIs. These building blocks enable memory, semantic search, tool execution, and scalable behavior — all essential for agents that must work reliably in production.
AI agents are more than prompts and outputs. They are backed by an ecosystem that supports reasoning, long-term memory, and dynamic tool use. Embeddings, vector databases, and frameworks are the foundation that lets agents retrieve knowledge, store context, and scale across systems. Without these components, agents remain largely stateless and limited in capability.
***
## Why these technologies matter
A modern agent must:
* Understand unstructured data (text, images, audio)
* Search and filter large memories or corpora by meaning
* Maintain short- and long-term context for multi-step tasks
* Interact with external tools and services reliably
These capabilities are enabled by the foundational technologies described below.
***
## Embeddings — the semantic glue
Embeddings map text, images, or audio into dense numerical vectors that capture semantic meaning. For example, the vectors for “dog” and “puppy” will be closer in vector space than “dog” and “car”. Agents use embeddings to:
* Compare concepts by similarity
* Retrieve related documents or past interactions
* Make context-aware decisions and rank responses
Embeddings power semantic search, contextual matching, relevance ranking, recommendations, and many other downstream tasks required by memory-enabled agents.
Embedding models convert varied data types (images, documents, audio) into numerical vectors learned by neural networks. These high-dimensional vectors are typically stored in a vector database where their meaning is implicit in relative position. By measuring distances or similarity metrics between vectors, agents perform nearest-neighbor searches to find semantically similar items — enabling search relevance, recommendations, and classification.
***
## Vector databases — persistent, performant semantic stores
Vector databases store and index embeddings for fast, scalable semantic retrieval. When an agent needs to remember something or find related concepts, it queries a vector DB with an embedding and retrieves results by semantic proximity rather than exact keyword matches. This is essential for agents working with large corpora such as documents, chat history, or logs.
Vector DBs are the backbone of agent memory patterns like RAG, tool chaining, and long-term context handling.
Examples:
* Pinecone — managed vector DB optimized for production
* Chroma — developer-friendly open source vector store
* Milvus — scalable open-source vector database for enterprise
***
## Cloud providers and vector search offerings
Major cloud providers or ecosystems offer native vector search or integrate with vector providers:
* AWS: Amazon Kendra, Amazon OpenSearch Service (K-NN), and Bedrock integrations
* Azure: Azure Cognitive Search and Azure AI Studio, integrated with OpenAI embeddings
* Google Cloud: Vertex AI Matching Engine and third-party integrations (e.g., Pinecone)
These platforms let you store embeddings, perform similarity searches, and scale memory-intensive tasks — which is crucial for production agents with high query volumes or strict data residency requirements.
***
## Traditional databases vs. vector databases
Traditional OLTP/OLAP databases are built for structured data (transactions, user records, analytics) and excel at schema-driven queries. They are not optimized for semantic search over unstructured content like PDFs, audio transcriptions, or images.
Vector databases complement traditional systems by converting unstructured content into embeddings and enabling similarity-based retrieval for:
* Document search and RAG
* Recommendations and personalization
* Contextual retrieval for chat/history
Table: Quick comparison
| Feature | Traditional DB (SQL/NoSQL) | Vector DB |
| ----------- | ---------------------------------- | -------------------------------------- |
| Best for | Structured records, transactions | Unstructured semantic search |
| Query style | Exact match, aggregations | Nearest-neighbor / similarity |
| Use cases | Billing, configurations, analytics | RAG, recommendations, search relevance |
| Example | `SELECT * FROM users WHERE id = 1` | `query(embedding_vector)` |
Note: Use traditional DBs for transactional integrity and configuration; use vector DBs for meaning-based retrieval.
***
## Agent frameworks, orchestration, and tooling
Agents need orchestration frameworks to plan actions, manage goals, and interact with tools. Popular frameworks include:
* OpenAI Agent SDK — goal-oriented, multimodal runtime with plugins and tracing
* LangChain — modular library for RAG, tool use, and chains
* AutoGen (Microsoft) — framework for multi-agent LLM collaboration and orchestration
These frameworks are typically used together with embeddings and vector DBs to implement memory, tool invocation, and multi-step reasoning.
***
## Retrieval-Augmented Generation (RAG)
RAG is a core pattern for agents that require contextual awareness beyond a single prompt. The typical RAG workflow:
1. Convert the user query into an embedding.
2. Retrieve relevant context from a vector DB using that embedding.
3. Pass the retrieved context and the original query to an LLM.
4. The LLM generates a response grounded in the retrieved information.
RAG merges generative LLM strength with persistent, factual external knowledge to reduce hallucination and keep responses current and verifiable.
***
## Choosing the right stack — practical guidance
Deciding on a backend and tools depends on requirements like memory persistence, multi-step reasoning, scale, latency, and data governance.
General recommendations:
* Long-term memory / document search → Embeddings + Vector DB
* Multi-step reasoning / tool orchestration → Use a framework (LangChain, OpenAI Agent SDK, AutoGen)
* Enterprise production → Leverage cloud provider vector offerings for integration, compliance, and scaling
When selecting components, consider latency, cost, data residency, refresh rates for embeddings, and how frequently your agents will write to or query the vector store. These operational factors strongly influence architecture choices.
Decision tree (high-level):
```text theme={null}
Start →
├─ Do you need long-term memory?
│ ├─ Yes → Use Embeddings + Vector DB
│ │ ├─ On AWS → Use Kendra / OpenSearch
│ │ ├─ On Azure → Use Cognitive Search
│ │ └─ On GCP → Use Vertex Matching Engine
│ └─ No → Use standard retrieval or local memory only
Then →
├─ Will your agent need tool execution and planning?
│ ├─ Yes → Use OpenAI Agent SDK / LangChain / other team-oriented frameworks
│ │ └─ Multiple agents? → Use team-oriented frameworks or AutoGen
│ └─ No → Use single-shot or RAG-style agents
Then →
├─ Do you need collaboration or workflow automation?
│ ├─ Yes → Choose frameworks that support multi-step plans (LangChain, AutoGen)
│ └─ No → Use simple agent loop (prompt → tool → respond)
```
***
## Typical agent architecture
A typical production agent connects the following components:
* User interface or API that captures user input
* Orchestration framework that plans steps and invokes tools
* Embedding model to convert queries and documents into vectors
* Vector database for memory and similarity retrieval
* External tools/services for executing actions (APIs, databases, business systems)
This modular architecture enables flexibility, scalability, and better separation of concerns between planning, memory, and execution.
Privacy and compliance matter: before storing user data or embeddings, confirm data residency, PII handling, and encryption requirements. Embeddings derived from sensitive data may still be sensitive — apply anonymization, access controls, and legal reviews.
***
## Links and references
* [Pinecone](https://www.pinecone.io) — managed vector database
* [Chroma](https://www.trychroma.com) — open-source vector store
* [Milvus](https://milvus.io) — scalable open-source vector DB
* [Amazon Kendra](https://aws.amazon.com/kendra/) / [OpenSearch](https://aws.amazon.com/opensearch-service/) / [Bedrock](https://aws.amazon.com/bedrock/)
* [Azure Cognitive Search](https://azure.microsoft.com/services/search/) / [Azure AI Studio](https://learn.microsoft.com/azure/ai-studio/)
* [Vertex AI Matching Engine](https://cloud.google.com/vertex-ai/docs/matching-engine)
* [OpenAI Agent SDK](https://platform.openai.com/docs/guides/agents)
* [LangChain](https://python.langchain.com/en/latest/)
* [AutoGen (Microsoft)](https://github.com/microsoft/autogen)
* [Retrieval-augmented generation (Wikipedia)](https://en.wikipedia.org/wiki/Retrieval-augmented_generation)
***
This overview should help you map the right components to your agent project. Focus on the combination of embeddings, a reliable vector store, and an orchestration framework to build memoryful, tool-capable agents that scale in production.
# Ethical Considerations
Source: https://notes.kodekloud.com/docs/AI-Agents/Prerequisites/Ethical-Considerations/page
Guidelines and best practices for ethical design, deployment, and oversight of AI agents to ensure safety, fairness, transparency, privacy, and accountability.
Welcome back.
This lesson covers the ethical considerations when designing and deploying AI agents. We’ll walk through why ethics matter, key principles, and practical controls to reduce harm across single-agent and multi-agent systems.
Topics covered:
* Why ethics matter in AI agent design
* Transparency and explainability in agentic systems
* Bias and fairness in agent decision making
* Privacy and data protection in agent architecture
* Autonomy versus human oversight
* Accountability and legal responsibility
* Ethical design for multi-agent systems
* Frameworks and standards for responsible AI agent development
Ethical design for AI agents is essential: it protects users, enables regulatory compliance, builds trust, and ensures systems remain safe and reliable as they scale.
Why ethics matter
AI agents are increasingly autonomous and embedded in everyday services. Unlike traditional programs that only execute explicit commands, agents can operate continuously, adapt strategies, and influence human outcomes. Without careful design and controls, agents can discriminate in hiring, mishandle personal data, or amplify harmful biases. Ethical design aligns agent behavior with societal values, reduces legal and operational risk, and fosters user trust and adoption.
Core principles of ethical AI
Use these core principles as a foundation when designing, training, testing, and deploying AI agents:
| Principle | What it means | Practical implementation examples |
| ------------------------- | -------------------------------------------------: | -------------------------------------------------------------------- |
| Privacy & data governance | Minimize collection and protect personal data | Data minimization, encryption, retention policies, role-based access |
| Fairness | Avoid biased or discriminatory outcomes | Diverse datasets, fairness-aware objectives, subgroup testing |
| Accountability | Clarify who is responsible for agent actions | Audit logs, owner/operator roles, contractual SLAs |
| Transparency | Make agent behavior observable and traceable | Action logs, provenance, tool-use records |
| Explainability | Provide human-understandable reasons for decisions | Decision summaries, rationale traces, confidence scores |
| Reproducibility | Ensure consistent, testable results | Versioned models, seed controls, test suites |
These pillars help teams develop and deploy AI systems responsibly, increasing reliability and safety.
Transparency and explainability
Explainability is critical for human trust and regulatory compliance—especially when agents rely on opaque models (e.g., LLMs). Design agents to record and expose decision trails: the reasoning steps, which tools were invoked, and the data inputs that influenced outputs. This traceability supports auditing, debugging, and meaningful human review.
Traceability is often required by law and safety best practices. Make logs structured and tamper-evident so stakeholders can trace how and why an agent reached a decision.
Best practices for explainability:
* Record the agent’s step-by-step reasoning and tool calls.
* Surface concise, human-readable rationales and confidence estimates.
* Link outcomes to supporting data or rules for auditors and end users.
Bias and fairness
Agents reflect the data, objectives, and constraints used to create them. If training data carries historical bias or goals are mis-specified, agents can perpetuate or amplify inequality.
For example, a hiring-screening agent trained on biased historical hiring data may unfairly favor certain demographics.
Mitigation strategies:
* Audit models and outputs across demographic groups and contexts.
* Curate diverse, representative datasets and document dataset provenance.
* Add fairness constraints or objective adjustments during training and evaluation.
* Use counterfactual, stress, and adversarial tests to detect hidden biases.
Privacy and data protection
AI agents often handle sensitive personal or organizational data, creating risks around storage, access, and unintended disclosure. Agents with persistent memory or web access must have clear limits on what they can store or share.
Recommended controls:
* Data minimization and purpose-limited retention.
* End-to-end encryption for data at rest and in transit.
* Strong access controls, least-privilege service accounts, and audit trails.
* Explicit memory policies (what can be remembered and for how long).
* Compliance checks for relevant regulations (e.g., [GDPR](https://gdpr.eu/), [HIPAA](https://www.hhs.gov/hipaa/index.html)).
Autonomy versus human oversight
Balance autonomous agent capabilities with human control based on risk level. Low-risk tasks (like routine telemetry checks) may justify higher autonomy; high-risk tasks (medical, legal, or financial decisions) typically require human-in-the-loop approval and clear escalation paths.
Design controls:
* Define control boundaries and decision thresholds that trigger human review.
* Provide obvious user overrides and emergency stop mechanisms.
* Log human interventions and outcomes to refine policies and thresholds.
Accountability and legal responsibility
Assign clear responsibility for agent design, deployment, and operation. When agents cause harm, it's important to determine whether liability rests with the developer, deployer, integrator, or model provider.
To support accountability:
* Produce immutable logs and provenance data for decisions and tool use.
* Maintain versioned model and dataset records for reproducibility.
* Define contractual responsibilities, SLAs, and incident response procedures.
* Include safety overrides and fallback behaviors to limit harm.
Explainability revisited
Explainability helps stakeholders understand not only what an agent decided, but why. Provide interpretable summaries that connect decisions to data sources or rule-based logic, and surface confidence scores to inform human reviewers. For regulated domains, prioritize explanations suitable for non-technical users (e.g., consumers, patients) as well as technical audit trails.
Multi-agent systems and emergent risks
When multiple agents interact, risks can increase—coordinated agents may reinforce biases, create unexpected behaviors, or produce cascading failures.
Design strategies for multi-agent safety:
* Filter and validate inputs exchanged between agents to prevent data poisoning.
* Audit inter-agent reasoning traces and recorded communications for anomalies.
* Use simulation and sandbox testing to discover emergent behaviors before production.
* Implement conflict-resolution protocols, rate-limiting, and fail-safes.
* Apply adversarial testing and resilience checks to harden against attacks.
Frameworks and standards
Adopt recognized frameworks and standards to guide development and compliance. Relevant sources include:
* [EU AI Act](https://digital-strategy.ec.europa.eu/en/policies/european-approach-artificial-intelligence)
* [OECD AI Principles](https://www.oecd.org/going-digital/ai/principles/)
* [NIST AI Risk Management Framework](https://www.nist.gov/itl/ai-risk-management-framework)
Many vendors and research labs publish responsible-AI policies and operational guidelines (for example, [OpenAI](https://openai.com/policies), [Anthropic](https://www.anthropic.com/policies), [Microsoft](https://www.microsoft.com/en-us/ai/responsible-ai)). These resources emphasize transparency, human-centered design, accountability, and harm minimization.
Developer checklist (quick reference):
* Define the agent’s intended purpose, permissible actions, and risk profile.
* Document datasets, model versions, and evaluation metrics.
* Implement logging, provenance, and explainability outputs.
* Apply privacy controls, encryption, and retention policies.
* Test for fairness, robustness, and adversarial resilience.
* Create human-in-the-loop and override mechanisms for high-risk decisions.
* Establish incident response, monitoring, and accountability assignments.
* Align deployment and documentation with relevant legal/regulatory frameworks.
Applying these principles across design, testing, deployment, and monitoring will help ensure AI agents are safe, fair, and trustworthy in real-world use.
# Testing and Evaluation of AI Agents
Source: https://notes.kodekloud.com/docs/AI-Agents/Prerequisites/Testing-and-Evaluation-of-AI-Agents/page
Practical guide to testing and evaluating AI agents, covering metrics, behavioral testing, tool and memory validation, human feedback, cost optimization, observability, scaling, and CI/CD integration.
Welcome back.
In this lesson we begin a practical exploration of testing and evaluating AI agents. We'll explain why testing matters, the core dimensions to measure, practical testing strategies, and how to operationalize evaluation in production.
High-level agenda:
* Why testing and evaluation matter for agents
* Key performance dimensions and metrics
* Behavioral testing, success criteria, and goal completion
* Tool use, memory, and reasoning validation
* Human feedback and UX testing
* Cost evaluation and optimization techniques
* Scaling agents across users, workloads, and environments
* Metrics, logs, and continuous monitoring strategies
* An evaluation pipeline and vendor/industry recommendations
* AI agents applied to software testing
Why test agents?
Testing and evaluation ensure agents behave as intended when they act autonomously. Without systematic validation, agents can hallucinate, misuse tools, leak sensitive data, or produce low-value or unsafe outputs. A robust testing pipeline increases reliability, accuracy, cost-efficiency, and trust — and helps maintain safe behavior across edge cases and production settings.
Agents differ from traditional software because they reason, plan multi-step actions, and orchestrate external tools and APIs. Therefore, agent evaluation must go beyond single-shot accuracy: you must assess behavior across sequences, intermediate steps, and tool interactions. Testing should be continuous: aligned with business goals, UX expectations, and safety constraints.
Testing agents is not a one-time QA step. Design evaluation as an ongoing feedback loop that includes automated checks, human review, and monitoring in production.
Key evaluation dimensions
Measure agents across multiple dimensions to capture behaviour, efficiency, and user impact. Below is a compact reference table for common metrics and what they reveal.
| Dimension | What to measure | Why it matters |
| ------------------------- | --------------------------------------------------------------------------: | ------------------------------------------------------------- |
| Task success | Success rate for defined goals (e.g., “schedule meeting”, “summarize docs”) | Measures whether the agent reaches the intended outcome |
| Correctness & reliability | Accuracy, reproducibility, error types | Detects hallucinations and inconsistent behavior |
| Tool usage | Which tools were called, arguments used, number of calls | Validates correct orchestration and surface area for failures |
| Latency | Time-to-first-response, time-to-completion | Affects UX and real-time interactivity |
| Cost & resources | Tokens per run, API call counts, compute costs | Enables cost–accuracy trade-offs and optimization |
| User satisfaction | Ratings, NPS, qualitative feedback | Captures subjective usefulness, tone, and trust |
Each metric reveals a different behavioral facet. Measure these both offline (benchmarks, unit tests) and in live deployment (A/B tests, canary releases).
Behavioral testing and edge cases
Behavioral testing assigns explicit goals and evaluates whether the agent achieves them across diverse conditions. Example: for the goal “summarize the top three articles about climate policy,” a robust agent must (1) find relevant articles, (2) synthesize content accurately, and (3) format the summary according to spec.
Edge-case and robustness tests are essential:
* Simulate missing or malformed inputs.
* Inject API errors and timeouts.
* Test ambiguous or conflicting instructions.
* Check permission and access-control failures.
Resilient agents should retry, escalate, or fail safely instead of hallucinating or returning misleading outputs. Build test harnesses that model network failures, malformed payloads, permission errors, and ambiguous prompts.
Tools, memory, and reasoning validation
Modern agents rely on external tools (search, calculators, schedulers), stateful memory stores, and multi-step reasoning. These introduce new failure modes:
* Wrong tool selection for subtasks
* Incorrect memory reads/writes that violate context boundaries
* Incoherent or non-deterministic reasoning chains
Validation checklist:
* Tool orchestration: Was the correct tool called with the right arguments?
* Memory correctness: Were relevant memories retrieved and updated consistently?
* Plan coherence: Do intermediate reasoning steps align with the final output?
Instrument agents with tracing and structured logs to capture planning steps, tool calls, and intermediate outputs. Use framework tracing (for example, LangChain tracing utilities: [https://python.langchain.com/](https://python.langchain.com/)) or your SDK’s agent tool-call logs to visualize and audit behavior.
Be cautious with memory and tool integrations: improperly isolated memory or unchecked tool outputs can leak sensitive information across sessions. Include privacy and access-control tests in your pipeline.
Human feedback and UX testing
Human evaluators capture subjective qualities like clarity, tone, and trustworthiness. Typical human-in-the-loop practices:
* Guided rating workflows where human raters score outputs on clarity, relevance, and reliability.
* UX sessions that record confidence, perceived helpfulness, and qualitative comments.
* A/B testing of prompts, personalities, and response formats to measure user preference.
Blend automated scoring with periodic human review—especially in early deployments or high-impact applications (customer support, internal automation). Human feedback surfaces blind spots such as ambiguous phrasing, offensive tone, or unexpected behavior.
Cost evaluation and optimization
At scale, cost and latency directly influence feasibility. Track these metrics per task:
* Tokens consumed
* API/tool call count per request
* External service and compute costs per completion
* Wall-clock time per completion
Optimization strategies:
* Route deterministic or trivial logic to rules-based code, not a model.
* Use tiered models: `GPT-3.5` (or similar) for simpler steps, larger models for complex reasoning.
* Cache frequent query results and tool outputs.
* Batch tool calls and memory accesses where safe.
Integrate cost metrics into evaluation so that optimizations explicitly trade off accuracy, latency, and cost.
Scaling agents across users and workloads
Scaling agents introduces concurrency, context separation, and multi-tenant safety concerns:
* Memory separation: ensure Agent A cannot access Agent B’s private data.
* Context switching: save and restore user contexts correctly under load.
* Throughput testing: validate performance with many parallel requests.
Cloud-native patterns help: vector databases for memory, horizontally scaled stateless services, async execution queues, and autoscaled model inference.
| Scaling concern | Pattern or tool |
| ----------------- | ----------------------------------------- |
| Context isolation | Vector DBs with tenant keys, strict ACLs |
| Concurrency | Async queues, worker pools, rate limiting |
| Throughput | Autoscaling inference, sharded caches |
Observability, metrics, and continuous monitoring
Post-deployment testing shifts to continuous monitoring. Key observability features:
* Structured logs per planning and execution step
* Token, tool, and latency tracking per run
* Failure-rate and error-pattern analytics
* Dashboards with KPIs: goal success, cost per task, average latency
Instrument agents to emit traces that include tool calls, intermediate reasoning, and memory operations. Configure alerts for KPI drifts and anomalous behavior so teams can remediate issues before they impact users.
Evaluation pipeline (test → run → score → optimize)
A recommended structured pipeline:
1. Define test prompts or goals (e.g., “schedule a meeting and send a confirmation email”).
2. Run the agent runtime, triggering planning, memory access, and tool usage.
3. Log every step: planning decisions, tool calls and responses, memory reads/writes, and intermediate outputs.
4. Score the run with automated checks (expected tool called, format matched) and/or human ratings (clarity, usefulness, accuracy).
5. Feed results into an optimization loop: refine prompts, fix orchestration bugs, reconfigure tools, or retrain/fine-tune models.
Traces are the foundation for debugging, metrics, and continuous improvement.
Industry guidance (summary)
Practical recommendations distilled from industry guidance:
1. Evaluate agents multidimensionally — measure correctness, tool usage, reasoning quality, and user trust, not just raw accuracy.
2. Use human-in-the-loop testing during early staging to reveal unclear responses and subtle biases.
3. Tie evaluation to cost and UX outcomes — prioritize solutions that balance effectiveness and efficiency.
4. Treat agents as dynamic ecosystems — implement continuous testing, observability, traceability, and drift detection.
These practices help keep agents trustworthy and sustainable at scale.
AI agents in software testing
AI agents are transforming software testing by interpreting requirements, generating tests, detecting bugs, and prioritizing test effort. Compared with static test scripts, agent-driven testing adapts more readily and explores edge cases more efficiently.
This diagram highlights an AI-driven software testing pipeline across four stages:
* Automate testing: agents run and manage test cases with less manual work.
* Analyze data: aggregate test outcomes to find patterns.
* Predict defects: prioritize high-risk components for testing.
* Generate test cases: create new tests from code changes or usage telemetry.
Feedback loops emphasize continuous learning — test outcomes inform future test generation and prioritization.
Capabilities of AI testing agents
AI testing agents can:
* Generate test cases from natural-language specifications.
* Detect bugs by analyzing logs, traces, and execution outputs.
* Integrate with test toolchains such as Playwright and Selenium, and with CI/CD.
* Produce structured bug reports with remediation suggestions.
* Learn from prior test runs to improve coverage and reduce false positives.
Testing workflow and CI/CD integration
A typical testing workflow:
1. Feed agents product requirements or user stories (structured or natural language).
2. Agents generate test cases and execute them through the test toolchain.
3. Outcomes are logged and analyzed; agents recommend fixes or test adjustments.
4. Integrate into CI/CD (for example, GitHub Actions: [https://docs.github.com/actions](https://docs.github.com/actions) or Jenkins: [https://www.jenkins.io/](https://www.jenkins.io/)) so tests run on code changes.
5. Agents adapt test cases over time using telemetry and observed outcomes.
Automating this loop increases test cadence and reduces manual upkeep.
Practical use cases and limitations
Common use cases:
* Regression testing at scale
* Exploratory testing to uncover edge-case bugs
* Visual/UI testing for layout and rendering regressions
* Generating human-readable reports and automated developer notifications
Limitations and challenges:
* Quality of output depends on input quality and precise requirement definitions.
* Complex business logic and nuanced edge cases often still require human oversight.
* Integrating agents with legacy monoliths can be difficult.
* Agents must be tuned to minimize false positives and negatives.
As models and frameworks mature, expect smoother CI/CD integration, greater self-adaptation, and agents acting as continuous QA copilots across the software lifecycle.
The future of AI-driven testing
Emerging capabilities that will shape future testing:
* Self-healing tests that adapt to code changes automatically.
* Automation of repetitive setup and verification tasks to speed cycles.
* Predictive analytics that forecast defect-prone areas.
* Natural-language-first testing to make test creation accessible to non-engineers.
* Continuous, real-time validation for faster feedback loops.
* Increased test coverage through adaptive exploration and prioritization.
* AI-driven optimization to refine test effectiveness continuously.
Together, these trends point to faster, more adaptive testing closely aligned with real-world usage and deployment patterns.
# Types of AI Agents
Source: https://notes.kodekloud.com/docs/AI-Agents/Prerequisites/Types-of-AI-Agents/page
Overview of AI agent types, their decision architectures, capabilities, and guidance on selecting simple reflex, model-based, goal-based, utility-based, learning, and autonomous agents.
Welcome back!
This lesson examines the common types of AI agents, their capabilities, and when to use each. We start with a classification overview, then cover simple reflex, model-based reflex, goal-based, utility-based, learning, and autonomous agents. Finally, we compare them to show the progression from reactive systems to fully autonomous agents.
Understanding agent classes clarifies levels of intelligence, autonomy, and adaptability. Distinguishing simple reflex agents from fully autonomous systems helps you select the right architecture for chatbots, robotics, automation pipelines, or research assistants.
## Agent classification overview
AI agents are commonly classified by complexity, decision-making approach, and degree of autonomy. Each class builds on the previous: from rule-based reactivity to internal models, goal-directed planning, utility optimization, learning, and ultimately autonomous operation.
* Keywords: AI agent types, reactive agents, goal-based planning, utility optimization, learning agents, autonomous systems.
* Benefit: Choose an agent type that matches task complexity and environment dynamics to build efficient, scalable systems.
## Simple reflex agents
Simple reflex agents act only on the current percept (the immediate sensor input) using condition-action rules like “if X then do Y.” They do not store state or reason about the future.
* Strengths: fast, predictable, low compute requirements in fully observable, static environments.
* Limitations: fail in partially observable or ambiguous settings; cannot plan or use history.
* Typical examples: motion-sensor lights, basic threshold-based controllers.
Reactive cycle:
1. Sensors receive percepts describing current conditions.
2. Agent applies condition-action rules to decide “what to do now?”
3. Actuators execute the chosen action.
4. Repeat with no memory or learning.
## Model-based reflex agents
Model-based reflex agents add an internal state (a world model) enabling them to handle partial observability and reason about effects of past actions.
* Strengths: better handling of stateful, partially observable tasks; more robust than simple reflex agents.
* Typical use: robots that track cleaned areas to avoid repetition.
* Implementation pattern: maintain and update an internal state based on percepts and known dynamics.
Reactive loop with an internal model:
1. Sensors provide percepts.
2. Agent updates its internal state (model of the world).
3. Based on state and rules, it selects an action.
4. Actuators execute the action, changing the environment.
## Goal-based agents
Goal-based agents decide by selecting actions that lead toward explicit objectives. They simulate or search future states to choose behaviors consistent with goals.
* Strengths: supports intentional planning and deliberative behavior; can evaluate alternative plans.
* Typical use: route planning, scheduling, complex problem solving.
Decision loop:
1. Sensors provide percepts and agent updates internal state.
2. Agent reasons about possible futures if it takes different actions.
3. Using defined goals, it selects the action expected to best achieve the goal.
4. Actuators perform the action and the environment evolves.
Goal-based agents are ideal for navigation, multi-step tasks, and any domain where planning toward a target state matters.
## Utility-based agents
Utility-based agents extend goal-based reasoning with a utility function that ranks outcomes numerically. They choose actions that maximize expected utility—balancing trade-offs like speed, safety, cost, or user preference.
* Strengths: compare multiple goal-achieving options and optimize based on preference/utility.
* Typical use: multi-criteria route selection, pricing decisions, decision-support systems.
Decision process:
1. Sensors report current percepts.
2. Agent predicts outcomes of candidate actions with its internal model.
3. Utility function evaluates desirability of each predicted outcome.
4. Agent selects the action that maximizes expected utility.
5. Actuators execute the action.
Utility-based approaches are especially valuable when several alternatives achieve the same goal but differ in risk, cost, or quality.
## Learning agents
Learning agents improve their behavior over time by observing outcomes and updating their decision policies. They combine action selection, evaluation, learning, and exploration.
Key components:
* Performance element: chooses and executes actions.
* Critic: measures performance against a standard and provides feedback.
* Learning element: updates the performance element using feedback.
* Problem generator: encourages exploratory actions to discover better strategies.
Learning cycle:
1. Sensors feed percepts to the performance element.
2. Agent acts and the critic evaluates results against performance metrics.
3. Learning element updates the policy or model based on feedback.
4. Problem generator introduces exploration to avoid local optima.
5. Updated actions execute via actuators; loop continues.
Learning agents are well-suited for dynamic environments like robotics, games, adaptive control, and recommendation systems.
## Autonomous agents
Autonomous agents integrate sensing, internal modeling, goal pursuit, utility evaluation, planning, and continuous learning to operate with minimal human supervision. They actively explore and alter their environment to achieve broad objectives.
How they differ from generation-only models:
* Unlike models that primarily generate content on request (e.g., generative models), autonomous agents act proactively to observe, plan, and execute multi-step processes.
* They maintain long-term state and context for ongoing tasks.
Typical capabilities:
* Combine modeling, goal reasoning, utility optimization, and learning.
* Plan for extended horizons and coordinate complex workflows.
* Maintain memory and context across tasks.
A common autonomous automation loop:
1. Execute: an execution agent pulls an incomplete task, performs it, and returns results.
2. Enrich and Store: system enriches results and stores them in a `vector database` for memory and retrieval.
3. Context Retrieval: context agents query the `vector database` to fetch relevant background for the next task.
4. Create & Prioritize: a task-creation agent generates new tasks from enriched results and a prioritization agent orders them.
5. Loop: prioritized tasks feed back into execution, repeating the cycle.
Autonomous agents enable end-to-end automation for research, IT troubleshooting, fleet coordination, and complex process automation.
## Quick comparison
| Agent type | Key capability | Best for | Example |
| -----------------: | --------------------------------------------- | ----------------------------------- | -------------------------------------------------- |
| Simple reflex | Immediate condition-action rules | Highly observable, static tasks | Motion-activated light |
| Model-based reflex | Internal state for partial observability | Stateful robotic tasks | Vacuum robot tracking cleaned areas |
| Goal-based | Planning toward explicit goals | Navigation, scheduling | Route planning |
| Utility-based | Optimize choices with a utility function | Multi-criteria optimization | Route selection balancing speed and safety |
| Learning | Improve behavior from feedback | Dynamic environments, games | Smart thermostat learning habits |
| Autonomous | Integrate planning, utility, learning, memory | Open-ended, long-horizon automation | Automated research or IT troubleshooting pipelines |
## When to choose each agent
* Use simple reflex agents when the environment is fully observable and rules suffice.
* Use model-based reflex agents when you need memory or to infer unobserved state.
* Use goal-based agents when explicit objectives and planning are required.
* Use utility-based agents when you must compare trade-offs across multiple objectives.
* Use learning agents when performance must improve from experience or when the environment changes.
* Use autonomous agents for complex, long-running workflows that require coordination, memory, and self-directed task generation.
## Links and references
* [Generative models vs. autonomous agents](https://learn.kodekloud.com/user/courses/mastering-generative-ai-with-openai)
* [Vector databases for memory and retrieval in agent systems](https://learn.kodekloud.com/user/courses/vector-database-for-genai)
Understanding these agent classes helps you select and design the right architecture for your task: from simple reactive controllers to fully autonomous systems that plan, optimize, and learn.
# Types of Agentic Agents and Multi Agentic Agents
Source: https://notes.kodekloud.com/docs/AI-Agents/Prerequisites/Types-of-Agentic-Agents-and-Multi-Agentic-Agents/page
Overview of autonomous, goal-driven AI agents, their architectures, behaviors, distinctions from standard AI, components, workflows, and real-world use cases for multi-agent systems
In this lesson we examine agentic agents — autonomous, goal-driven AI systems — and how they differ from traditional AI. You'll learn:
* What agentic agents are
* How they compare to standard AI systems
* Core architecture and modular components
* Types of agentic behavior (goal-oriented, tool-using, self-improving)
* Practical, real-world use cases and a working agent loop example
Why agentic agents matter
Agentic agents represent a shift from reactive models to proactive, autonomous systems. Instead of answering one-off prompts, these agents accept goals, plan multi-step actions, use external tools, maintain memory, and adapt over time. That makes them suited for AI copilots, orchestration across services, and multi-agent ecosystems where long-running objectives and coordination are required.
As organizations build AI copilots and multi-agent workflows, mastering agentic design is essential for innovation, reliability, and scalability.
What are agentic agents?
Agentic agents are AI systems that operate with autonomy, intentionality, and goal orientation. They:
* Initiate actions without explicit prompt for each step
* Formulate and adapt plans
* Sense and reason about their environment
* Execute tasks using available tools and services
* Learn and refine strategies over time
Their behavior emerges from integrating memory, reasoning, tool invocation, and execution in a continuous control loop.
Core architecture of agentic systems
Agentic workflows are typically pipeline-driven and modular to support scaling, observability, and safe tool access:
* Data pipelines ingest and clean structured and unstructured sources.
* A Feature Store provides reusable, versioned features.
* Model experimentation and a model store support reproducibility.
* The Agentic AI Core handles language understanding, planning, and decision-making.
* Microservices and serverless functions enable event-driven, modular execution.
* Hybrid cloud infrastructure supports scale, locality, and compliance.
* Logging, auditing, monitoring, and front-end applications provide observability and human-in-the-loop controls.
Key architecture components and their roles:
| Component | Purpose | Example |
| ------------------------ | -------------------------------------- | ---------------------------- |
| Data pipelines | Ingest and clean inputs (batch/stream) | ETL jobs, Kafka streams |
| Feature store | Shareable features for models | Time-series feature store |
| Model store & deployment | Versioned models and serving | Model registry, model server |
| Agentic AI Core | Planning, reasoning, decision logic | LLM + orchestration engine |
| Tooling & microservices | External API access and execution | Search, DB, code runner |
| Observability | Audit trails, monitoring, alerts | Logging, APM, dashboards |
Agentic vs. standard AI systems
Agentic agents differ from traditional reactive systems along three core dimensions:
| Trait | Agentic agents | Standard AI systems |
| ----------- | ----------------------------------------------------- | ------------------------------------------ |
| Autonomy | Self-directed; continue work without repeated prompts | Reactive; perform a single task per prompt |
| Tool usage | Dynamically invoke APIs, search, code execution | Limited or no tool invocation |
| Persistence | Memory across sessions; long-term goals | Stateless or short-lived context |
Because of these traits, agentic agents act more like collaborators: they can decompose open-ended tasks, iterate on feedback, and coordinate with other systems or agents.
Real-world distinction
* Standard chatbot: answers a given question and stops.
* Agentic system: given "produce a market research report," it decomposes the task, collects data, synthesizes findings, and outputs a formatted report—adapting along the way as new information appears.
Core components of an agentic agent
Agentic solutions are modular. Typical components include:
| Component | Responsibility | Typical implementation |
| --------------------- | ------------------------------------- | -------------------------------------------- |
| Goal Management | Accepts, generates, prioritizes goals | Goal queue, scheduler |
| Planning Engine | Evaluates paths and decomposes tasks | LLM planning + rule engine |
| Action Execution | Runs tools and external calls | API clients, serverless functions |
| Memory Systems | Store context and outcomes | Short-term cache, long-term DB |
| Tool Invocation | Dynamically select and call tools | Search, DB, code runner, connectors |
| Learning & Adaptation | Improve from feedback & data | Reinforcement learning, retraining pipelines |
These components together enable persistence, flexibility, and robust decision-making in dynamic environments.
Types of agentic behavior
Agentic behavior typically spans three overlapping dimensions:
* Goal-oriented: set objectives, plan steps, re-evaluate strategies.
* Tool-using: select and operate tools such as web search, databases, or code execution.
* Self-improving: learn from outcomes, monitor metrics, and refine strategies over time.
High-performing agents combine these behaviors to handle complex, multi-step objectives efficiently.
Capability breakdown
An agent integrates multiple capabilities to perceive, reason, and act:
* Autonomy: self-organization and independent operation.
* Memory: short-term and long-term contextual storage.
* Action: execute tasks, call functions, and reflect on outcomes.
* Goal focus: maintain objectives and respect constraints.
* Planning: chain-of-thought reasoning, task decomposition, sequencing.
* Skills: access tools such as web search, code execution, summarizers, and data retrieval.
Use cases
Agentic agents add value where ongoing autonomy, orchestration, or long-horizon planning matters:
* Business automation: schedule coordination, meeting summaries, automatic follow-ups.
* AI research assistants: plan experiments, search literature, debug code, produce reports.
* Customer service orchestration: detect trends, escalate issues, draft stakeholder communications.
* Productivity bots: personal assistants that plan calendars, book appointments, summarize emails.
* Autonomous operations: monitor infrastructure, restart services, report anomalies.
Industries benefiting from agentic AI include customer service, healthcare, retail, manufacturing, marketing, HR, finance, insurance, and logistics.
Agentic workflow example (agent loop)
A typical agent loop:
1. Goal Initialization — Agent receives or generates a goal (e.g., "Summarize the top five AI news articles").
2. Environment Sensing — Collect data from APIs, web, or files.
3. Planning & Reasoning — Decompose the goal into subtasks (LLM + logic engine).
4. Tool Selection & Action Execution — Run searches, call APIs, execute code, summarize results.
5. Memory Update — Log context, actions, and outcomes.
6. Evaluation & Feedback — Measure success, adjust approach, iterate.
This loop repeats until the goal is satisfied or re-prioritized. Example flowchart:
```mermaid theme={null}
flowchart TD
A[Goal Initialization
(User-defined or self-generated)] --> B[Environment Sensing
(Text, APIs, Files, Web)]
B --> C[Planning & Reasoning
(LLM + logic engine)]
C --> D[Tool Selection & Action Execution
(APIs, code, search, write)]
D --> E[Memory Update
(Log context, results, failures)]
E --> F[Evaluation & Feedback
(Was the goal met? Adjust?)]
F --> A
```
In production, agents select tools dynamically (search engines, databases, code runners), persist context to memory stores, and use evaluation metrics to determine next steps.
Agentic systems are most effective when goals, constraints, and evaluation metrics are well defined. Observability (logging, monitoring) and safe tool access controls are critical for reliable deployments.
Links and references
* [Multi-agent systems (overview)](https://en.wikipedia.org/wiki/Multi-agent_system)
* [Designing autonomous agents](https://www.acm.org/) (research & best practices)
* [LLM-based agents and tool use](https://platform.openai.com/docs/guides/agents)
# Ansible Playbook Basics
Source: https://notes.kodekloud.com/docs/AI-Assisted-Ansible/Ansible-Refresher/Ansible-Playbook-Basics/page
Overview of Ansible playbooks covering structure, components, execution, and best practices for automating system configuration and application deployment
In this lesson we focus on one of the most important parts of Ansible: playbooks. Understanding how playbooks are structured and how they execute gives you a reliable foundation to automate system configuration, application deployment, and operational tasks.
What is a playbook?
Think of a playbook as an automation blueprint: a human-readable, declarative description of the desired end state for one or more hosts. Ansible evaluates the declaration and makes the remote systems match that state. Playbooks use YAML for readability and maintainability so teams can review, share, and version control automation easily.
Key benefits of using playbooks
* Consistency: Running the same playbook produces the same result every time.
* Scale: Apply the same configuration across many hosts in a single run.
* Idempotence: Re-running a playbook leaves systems unchanged when they already match the desired state.
* Readability: Playbooks double as documentation for what your automation does.
Basic skeleton of a playbook
A playbook is one or more plays, and a play targets one or more hosts. At minimum, a play typically contains:
* `name`: a descriptive label for the play
* `hosts`: the inventory group or host pattern to target
* `become`: whether to use privilege escalation (e.g., sudo)
* `tasks`: a list of steps (each task calls a module)
Every playbook begins with the YAML document marker `---`.
Example minimal playbook:
```yaml theme={null}
---
- name: My play
hosts: all
become: true
tasks:
- name: Ensure nginx is installed
apt:
name: nginx
state: present
```
Everything else — variables, handlers, roles, loops, and conditionals — builds on this same foundation.
Playbook components explained
Below is a quick reference for the main building blocks you’ll use in playbooks.
| Component | Purpose | Common examples |
| -------------------- | ------------------------------------------------------------- | ------------------------------------------------ |
| Tasks | Ordered steps executed on target hosts | Use modules like `apt`, `yum`, `file`, `service` |
| Modules | Idempotent units that perform actions | `apt`, `copy`, `template`, `uri` |
| Handlers | Tasks triggered only when notified (useful for restarts) | `notify: Restart nginx` |
| Roles | Directory layout for reusable code and separation of concerns | `roles/nginx/tasks/main.yml` |
| Variables | Parameterize values across environments | Inventory vars, `vars_files`, `host_vars` |
| Loops & Conditionals | Iterate or run tasks conditionally to avoid duplication | `loop`, `when` |
Running and validating playbooks
Use `ansible-playbook` to execute playbooks. Before applying changes to real systems, validate syntax and structure.
Commands:
```bash theme={null}
# Run a playbook
ansible-playbook site.yml
# Check playbook syntax without connecting to hosts
ansible-playbook --syntax-check site.yml
```
Quick command references
| Task | Command |
| --------------- | ------------------------------------------ |
| Run a playbook | `ansible-playbook site.yml` |
| Syntax check | `ansible-playbook --syntax-check site.yml` |
| Check inventory | `ansible-inventory --list -i inventory/` |
Best practices and habits
Adopt these habits to keep playbooks reliable and maintainable:
* Always include a `name` for plays and for every task — it improves readability and troubleshooting.
* Run `ansible-playbook --syntax-check` before applying changes.
* Use handlers to avoid unnecessary service restarts when multiple tasks might trigger the same action.
* Prefer loops and conditionals over duplicating similar tasks to keep your playbooks concise and adaptable.
Additional tips:
* Keep roles focused and small; one role should do one job.
* Use `check_mode` (`ansible-playbook --check`) for dry runs where appropriate.
* Store secrets in Ansible Vault and avoid committing secrets to version control.
* Keep host- and group-level variables in separate `host_vars/` and `group_vars/` directories for clarity.
Conclusion
These fundamentals — structure, modules, handlers, roles, variables, and the habit of validating before running — are the building blocks of effective Ansible automation. Once comfortable with these basics, you can expand into advanced topics like custom modules, dynamic inventories, and complex role reuse.
Further reading
* [Ansible Documentation — Playbooks](https://docs.ansible.com/ansible/latest/user_guide/playbooks.html)
* [YAML Official Specification](https://yaml.org/spec/)
* [Ansible Best Practices](https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html)
# Demo Writing a Simple Playbook
Source: https://notes.kodekloud.com/docs/AI-Assisted-Ansible/Ansible-Refresher/Demo-Writing-a-Simple-Playbook/page
Tutorial showing how to create an Ansible playbook to install and configure Apache on RHEL, deploy a template index page, and manage the service with handlers.
Now that you understand what an Ansible playbook is and how its structure works, let's build one from a real-world scenario. This tutorial converts a repetitive manual process into automation so you can deploy a basic web test environment consistently across RHEL hosts.
Imagine a small fleet of RHEL servers where developers often need a disposable web test site. Currently someone manually installs Apache (httpd), enables and starts the service, and drops a test page. We'll automate those steps with a single Ansible playbook.
What you'll build
* A small Ansible project that installs httpd, deploys a template-based index.html, ensures the service is running, and restarts httpd when content changes.
* The playbook demonstrates inventory, ansible.cfg defaults, variables, tasks, templates, and handlers—the core building blocks of Ansible automation.
Workflow
* Create a project folder and basic files.
* Define an inventory that targets the managed host(s).
* Add a minimal ansible.cfg so you don't need extra CLI flags.
* Write a playbook with tasks and handlers.
* Run the playbook and verify the result on the managed host.
Environment overview
| Item | Details |
| -------------------- | ------------------------------------------- |
| Control host | Where Ansible runs (your workstation) |
| Managed host | servera (RHEL) |
| Authentication | SSH public-key authentication preconfigured |
| Remote user | student (passwordless sudo configured) |
| Privilege escalation | sudo via sudoers drop-in (no password) |
Ensure the Ansible remote user can perform privileged tasks. In this lab the sudoers entry allows the student user to use sudo without a password:
```text theme={null}
student ALL=(ALL) NOPASSWD: ALL
```
Be careful granting NOPASSWD sudo in production. Use the minimum required privileges and restrict commands where possible.
Install Ansible Core (example)
* Install Ansible on the control host. The example below uses dnf on RHEL; replace with your platform's package manager if needed.
```text theme={null}
student@control:~$ sudo dnf install -y ansible-core
...
Installed:
ansible-core-1:2.16.14-1.el10.noarch ...
Complete!
student@control:~$
```
Create the project directory and files
1. Create a project folder and enter it:
```bash theme={null}
student@control:~$ mkdir project
student@control:~$ cd project
```
2. Create an inventory file. This example defines a webservers group with servera. Adjust ansible\_host if you need an explicit IP.
```ini theme={null}
# inventory
[webservers]
servera ansible_host=10.0.2.4
```
3. Create a minimal ansible.cfg so you don't need to pass --inventory or --user on the command line. Save this as ansible.cfg in the project folder.
```ini theme={null}
[defaults]
inventory = inventory
remote_user = student
[privilege_escalation]
become = true
become_user = root
become_method = sudo
become_ask_pass = false
```
Files you will create
| File | Purpose |
| ------------- | ----------------------------------------------------------------- |
| inventory | Defines target hosts (webservers group) |
| ansible.cfg | Project-local defaults (inventory, remote\_user, become settings) |
| playbook.yml | The Ansible playbook with tasks and handlers |
| index.html.j2 | Jinja2 template for the web page |
Write the playbook
Create playbook.yml with the content below. The playbook installs the httpd package, deploys a simple index.html template, starts the httpd service, and notifies a handler to restart httpd when the template changes.
```yaml theme={null}
# playbook.yml
- name: install httpd on servera
hosts: webservers
vars:
httpd_pkg: httpd
httpd_svc: httpd
tasks:
- name: Install Apache webserver
dnf:
name: "{{ httpd_pkg }}"
state: latest
- name: Deploy content
template:
src: index.html.j2
dest: /var/www/html/index.html
notify: restart httpd
- name: Start httpd service
service:
name: "{{ httpd_svc }}"
state: started
handlers:
- name: restart httpd
service:
name: "{{ httpd_svc }}"
state: restarted
```
Create the template
Create the Jinja2 template index.html.j2 in the same project directory. This template uses an Ansible facts variable to include the host's hostname in the page.
```jinja2 theme={null}
Hello from {{ ansible_hostname }}
```
Validate and run the playbook
1. Perform a syntax check:
```bash theme={null}
student@control:~/project$ ansible-playbook playbook.yml --syntax-check
playbook: playbook.yml
```
2. Run the playbook:
```bash theme={null}
student@control:~/project$ ansible-playbook playbook.yml
```
Example (condensed) output showing the play execution:
```text theme={null}
PLAY [install httpd on servera] ****************************************************
TASK [Gathering Facts] *************************************************************
ok: [servera]
TASK [Install Apache webserver] ****************************************************
changed: [servera]
TASK [Deploy content] **************************************************************
changed: [servera]
TASK [Start httpd service] *********************************************************
changed: [servera]
RUNNING HANDLER [restart httpd] ***************************************************
changed: [servera]
PLAY RECAP ************************************************************************
servera : ok=5 changed=4 unreachable=0 failed=0 skipped=0
```
Verify the result on the managed host
SSH to the managed host (or use a remote check) and curl the local web server to confirm the template is served:
```bash theme={null}
student@control:~/project$ ssh servera
student@servera:~$ curl -s http://localhost
Hello from servera
```
This confirms the playbook installed httpd, deployed the index.html template, started the service, and the handler restarted httpd after the template changed.
Conclusion
You've created a minimal, reusable Ansible project that automates installing and configuring an Apache-based test page on RHEL. This covers essential Ansible concepts—inventory, configuration, variables, tasks, templates, and handlers—that form the foundation for more advanced automation.
Links and references
* [Ansible Documentation](https://docs.ansible.com/)
* [Ansible Playbooks](https://docs.ansible.com/ansible/latest/user_guide/playbooks.html)
* [Jinja2 Template Documentation](https://jinja.palletsprojects.com/)
* [RHEL System Administration Guide](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/)
# Demo Integrating Claude Code CLI
Source: https://notes.kodekloud.com/docs/AI-Assisted-Ansible/Claude-Code-CLI-With-Ansible/Demo-Integrating-Claude-Code-CLI/page
Demo guiding DevOps engineers to install and authenticate Claude Code CLI, generate and validate Ansible ad-hoc commands and playbooks from the terminal.
In this lesson you'll add Claude Code to an Ansible workflow so you can generate ad-hoc commands and playbooks directly from the terminal. Claude Code is a lightweight CLI client for Anthropic's Claude models that connects to the Claude API and helps developers author scripts, playbooks, and commands without leaving their shell.
Target audience: systems engineers and DevOps practitioners managing Linux servers across multiple environments who want to pilot AI-assisted automation to speed up routine tasks.
What you will do in this demo:
* Verify required system packages and environment
* Install the Claude Code CLI
* Authenticate the CLI (interactive browser flow)
* Validate Claude-generated Ansible ad-hoc commands and playbooks
## 1. Prepare the VM and shell
Switch to the student virtual machine and ensure you are in the home directory:
```bash theme={null}
student@control:~/claude$ cd ~
student@control:~$ clear
```
## 2. Install Claude Code CLI
Install the CLI using the official installer script (curl piped to bash):
```bash theme={null}
student@control:~$ curl -fsSL https://claude.ai/install.sh | bash
```
Sample installer output:
```output theme={null}
Setting up Claude Code...
✔ Claude Code successfully installed!
Version: 2.0.37
Location: ~/.local/bin/claude
Next: Run claude --help to get started
✅ Installation complete!
student@control:~$
```
## 3. Authenticate the CLI
Start the interactive login flow:
```bash theme={null}
student@control:~$ claude login
```
The CLI presents the login options:
```output theme={null}
Claude Code can be used with your Claude subscription or billed based on API usage through your Console account.
Select login method:
› 1. Claude account with subscription · Pro, Max, Team, or Enterprise
2. Anthropic Console account · API usage billing
```
Choose the appropriate method. In this demo the user selects a Claude account and authenticates via Google; a browser window opens for the OAuth flow.
After completing the browser-based login, the CLI displays security notes describing model limitations and guidance.
Claude models can make mistakes and prompts might include unsafe instructions. Be cautious when executing generated code or granting filesystem access.
Allow the CLI the requested workspace permissions, complete the flow, and return to the shell. If the process is interrupted you may see:
```text theme={null}
> /login
└ Login interrupted
student@control:~$
```
Re-run `claude login` to retry if needed.
## 4. Quick verification: ask Claude for Ansible ad-hoc commands
Try a simple prompt to generate an Ansible ad-hoc ping command for your inventory:
```bash theme={null}
student@control:~$ claude -p "Ansible ad-hoc command to ping all hosts within inventory"
```
Claude typically returns several valid variations. Common examples include:
| Use case | Command |
| ---------------------------------: | ---------------------------------------------- |
| Ping all hosts (default inventory) | ansible all -m ping |
| Ping all hosts using become (sudo) | ansible all -m ping --become |
| Ping a specific group (webservers) | ansible webservers -m ping |
| Ping as a specific user | ansible all -m ping -u username |
| Ping with verbose output | ansible all -m ping -v |
| Prompt for SSH password | ansible all -m ping --ask-pass |
| Prompt for become password | ansible all -m ping --become --ask-become-pass |
Note on the Ansible ping module:
* The `ping` module does not send ICMP packets; it executes a small Python task on the remote and returns "pong" on success. It verifies:
* SSH connectivity
* SSH authentication
* Python availability on the remote host
If your inventory doesn't match Claude's suggested pattern, Ansible will warn that the host pattern couldn't be matched:
```bash theme={null}
student@control:~$ ansible webservers -m ping
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
[WARNING]: Could not match supplied host pattern, ignoring: webservers
```
Inspect your workspace inventory to confirm host groups:
```bash theme={null}
student@control:~$ cd claude/
student@control:~/claude$ ls
ansible.cfg inventory site.yml
student@control:~/claude$ ansible webservers -m ping
# (runs against hosts defined in inventory)
```
## 5. Interactive mode: compose playbooks with natural language
Run `claude` without flags to enter interactive mode. Use plain language or slash commands to control behavior and persist prompts:
```text theme={null}
Claude Code v2.0.37
Welcome back andrei!
Sonnet 4.5 · Claude Pro
/home/student/claude
Tips for getting started
Run /init to create a CLAUDE.md file with instructions for Claude
Run /install-github-app to tag @claude right from your Github issues and PRs
Recent activity
No recent activity
> Try "fix lint errors"
? for shortcuts Thinking on (tab to toggle)
```
Ask Claude to generate a small Ansible playbook. Example prompt:
```text theme={null}
> As a DevOps engineer, generate a small Ansible playbook which creates the user test within the group webservers
```
Claude may produce a draft like this:
```yaml theme={null}
- name: Create test user in webservers group
hosts: all
become: yes
tasks:
- name: Ensure webservers group exists
ansible.builtin.group:
name: webservers
state: present
- name: Create test user and add to webservers group
ansible.builtin.user:
name: test
group: webservers
state: present
create_home: yes
shell: /bin/bash
```
If you intended to target the `webservers` host group (not create a system group), update the playbook to set `hosts: webservers` and remove the group-creation task. Corrected example:
```yaml theme={null}
- name: Create test user on webservers
hosts: webservers
become: yes
tasks:
- name: Create test user and add to webservers group
ansible.builtin.user:
name: test
group: webservers
state: present
create_home: yes
shell: /bin/bash
```
Save the playbook (for example, `create_user.yml`) and run it against your inventory:
```bash theme={null}
student@control:~$ ansible-playbook -i inventory create_user.yml
```
This demonstrates how Claude Code can draft useful Ansible content that you then review and refine before applying to your environment.
## Troubleshooting tips
* If `claude` is not found after installation, ensure `~/.local/bin` is in your PATH:
```bash theme={null}
echo $PATH
export PATH=$HOME/.local/bin:$PATH
```
* If browser login fails, try the alternate login method (Anthropic Console) or re-run `claude login`.
* Always review generated code for security, prompt injection, and correctness before executing.
## Helpful commands summary
| Action | Command |
| ----------------------- | ------------------------------------------------------------------------------- |
| Install Claude Code | curl -fsSL [https://claude.ai/install.sh](https://claude.ai/install.sh) \| bash |
| Authenticate CLI | claude login |
| Quick prompt from shell | claude -p "your prompt here" |
| Interactive mode | claude |
| Run playbook | ansible-playbook -i inventory create\_user.yml |
## Links and references
* [Anthropic Claude](https://claude.ai/)
* [Claude Code docs (install/login)](https://claude.ai/docs)
* [Ansible Documentation — ad-hoc commands](https://docs.ansible.com/ansible/latest/cli/ansible.html)
* [Ansible Documentation — playbooks](https://docs.ansible.com/ansible/latest/user_guide/playbooks.html)
This concludes the demo. You have installed and authenticated the Claude Code CLI, used it to generate Ansible ad-hoc commands and a playbook, and learned how to refine and run the output in your environment.
Congratulations!
# Demo Writting Playbook With Claude Code Cli
Source: https://notes.kodekloud.com/docs/AI-Assisted-Ansible/Claude-Code-CLI-With-Ansible/Demo-Writting-Playbook-With-Claude-Code-Cli/page
Guide to using Claude Code CLI to generate, refactor, lint, and run an Ansible playbook that installs and configures Apache httpd on RHEL hosts.
In this lesson you will use the Claude Code For Beginners CLI to generate and refine an Ansible playbook that installs and configures the Apache (httpd) web server on RHEL-based hosts. The walkthrough covers setting up a control-node workspace, generating a baseline playbook with Claude Code, refactoring to best practices (FQCNs, templates, lineinfile, handlers), validating, and running the playbook.
Overview — workflow
* Create a working directory and inventory
* Configure ansible.cfg
* Use Claude Code to generate site.yml (the playbook)
* Validate and refactor the playbook (use FQCNs, add template, lineinfile, handlers)
* Run ansible-lint / validate
* Execute the playbook and verify the result
For quick reference, here’s the workflow in a compact table:
| Step | Action | Why |
| ---- | -------------------------------------- | ---------------------------------------------------- |
| 1 | Create workspace + inventory | Tell Ansible which hosts to manage |
| 2 | Configure ansible.cfg | Ensure consistent behaviour and privilege escalation |
| 3 | Generate site.yml via Claude Code | Quickly scaffold a working playbook |
| 4 | Refactor (FQCNs, template, lineinfile) | Improve clarity, maintainability, and idempotence |
| 5 | Lint/validate | Catch issues early with ansible-lint |
| 6 | Run playbook and verify | Confirm the web server is configured correctly |
Preparation — create the control-node workspace
Run these commands in your Claude Code workspace to create a working directory and files:
```bash theme={null}
student@control:~/claude$ pwd
/home/student/claude
student@control:~/claude$ vim inventory
student@control:~/claude$ vim ansible.cfg
student@control:~/claude$ claude
```
Example inventory (inventory)
```ini theme={null}
[webservers]
servera
```
Example ansible.cfg
```ini theme={null}
[defaults]
inventory = inventory
[privilege_escalation]
become = true
become_user = root
become_method = sudo
become_ask_pass = false
```
Generate an initial playbook with Claude Code
Start an interactive Claude Code session and ask it to create a playbook named site.yml that installs httpd on hosts in the webservers group (RHEL-based systems). Example CLI snippet:
```bash theme={null}
student@control:~/claude$ claude
Claude Code v2.0.37
Welcome back andrei!
/home/student/claude
> Create an ansible playbook file called site.yml which installs httpd on the group of hosts called webservers which are RHEL-based systems.
```
Claude Code will typically generate a simple playbook like this. Open site.yml in your editor to inspect it.
Initial generated site.yml
```yaml theme={null}
---
- name: Install and configure httpd on webservers
hosts: webservers
become: yes
tasks:
- name: Install httpd package
yum:
name: httpd
state: present
- name: Start and enable httpd service
service:
name: httpd
state: started
enabled: yes
```
Refactor to use Fully Qualified Collection Names (FQCNs)
Best practice: use FQCNs such as ansible.builtin.yum and ansible.builtin.service to avoid ambiguity and ensure the intended module is executed. Ask Claude Code to refactor the playbook to FQCNs or update it yourself.
site.yml with FQCNs
```yaml theme={null}
---
- name: Install and configure httpd on webservers
hosts: webservers
become: yes
tasks:
- name: Install httpd package
ansible.builtin.yum:
name: httpd
state: present
- name: Start and enable httpd service
ansible.builtin.service:
name: httpd
state: started
enabled: yes
```
Add a Jinja2 template to serve host facts
Create a template that renders host-specific facts (hostname and fqdn) to /var/www/html/index.html. Example template (index.html.j2):
index.html.j2
```html theme={null}
Welcome
Welcome to {{ ansible_hostname }}
This page is served from host: {{ ansible_fqdn }}
```
Deploy the template and use lineinfile for attribution
Rather than embedding the attribution directly into the template, demonstrate combining modules: deploy the template using ansible.builtin.template, then add an attribution line using ansible.builtin.lineinfile. Notify a handler to reload httpd when the file changes.
Tasks to add
```yaml theme={null}
- name: Deploy index.html from template
ansible.builtin.template:
src: index.html.j2
dest: /var/www/html/index.html
owner: root
group: root
mode: '0644'
notify: Reload httpd
- name: Add attribution line to index.html
ansible.builtin.lineinfile:
path: /var/www/html/index.html
line: "This was created by ansible and claude"
insertbefore: '
Welcome to servera
This page is served from host: servera
This was created by ansible and claude
'
notify: Reload httpd
```
Add the handler
```yaml theme={null}
handlers:
- name: Reload httpd
ansible.builtin.service:
name: httpd
state: reloaded
```
Consolidated site.yml
Below is the full playbook that combines installation, service management, template deployment, line insertion, and the handler.
```yaml theme={null}
---
- name: Install and configure httpd on webservers
hosts: webservers
become: yes
tasks:
- name: Install httpd package
ansible.builtin.yum:
name: httpd
state: present
- name: Start and enable httpd service
ansible.builtin.service:
name: httpd
state: started
enabled: yes
- name: Deploy index.html from template
ansible.builtin.template:
src: index.html.j2
dest: /var/www/html/index.html
owner: root
group: root
mode: '0644'
notify: Reload httpd
- name: Add attribution line to index.html
ansible.builtin.lineinfile:
path: /var/www/html/index.html
line: "This was created by ansible and claude"
insertbefore: ''
notify: Reload httpd
handlers:
- name: Reload httpd
ansible.builtin.service:
name: httpd
state: reloaded
```
Linting and validation
Before running the playbook in production, consider running ansible-lint to catch common issues:
```bash theme={null}
ansible-lint site.yml
```
Execute the playbook
Run the playbook from your control node:
```bash theme={null}
student@control:~/claude$ ansible-playbook /home/student/claude/site.yml
```
Example playbook execution (trimmed)
```text theme={null}
PLAY [Install and configure httpd on webservers] ********************************
TASK [Gathering Facts] *********************************************************
ok: [servera]
TASK [Install httpd package] ***************************************************
changed: [servera]
TASK [Start and enable httpd service] ******************************************
changed: [servera]
TASK [Deploy index.html from template] *****************************************
changed: [servera]
TASK [Add attribution line to index.html] **************************************
changed: [servera]
RUNNING HANDLER [Reload httpd] *************************************************
changed: [servera]
```
Verify on the managed host
Confirm the web page is served and contains the expected facts and attribution.
```bash theme={null}
student@servera:~$ curl localhost:80