About this course
<p>If you've ever opened a 30-page PDF and thought, “There's absolutely no way I am reading all of this,” you already understand why file-analysis AI agents are useful.</p>
<p>Imagine uploading a research paper, résumé, CSV file, business report, or PDF and simply asking:</p>
<blockquote>
<p>“What are the most important findings?”</p>
</blockquote>
<p>Instead of manually searching through the document, an AI agent can inspect the file, understand what's inside it, and answer questions about it.</p>
<p>In this tutorial, we're going to build exactly that. We'll create a beginner-friendly <strong>AI file analysis agent in Python</strong> that can:</p>
<ul>
<li><p>Accept a file from your computer</p>
</li>
<li><p>Upload the file to an AI model</p>
</li>
<li><p>Read the contents of the file</p>
</li>
<li><p>Understand natural-language questions</p>
</li>
<li><p>Analyze the file</p>
</li>
<li><p>Return a useful answer</p>
</li>
<li><p>Handle different types of questions without us writing a separate function for every possible question</p>
</li>
</ul>
<p>We'll build the project using Python and the OpenAI API.</p>
<p>The important part is that we won't just copy and paste code and hope it works. We'll go through the code line by line so you understand what every important piece is doing.</p>
<p>By the end, you should understand not only how to build this project, but also the basic architecture behind many real-world AI agents.</p>
<h2 id="heading-what-well-cover">What We'll Cover:</h2>
<ul>
<li><p><a href="#heading-what-are-we-actually-building">What Are We Actually Building?</a></p>
</li>
<li><p><a href="#heading-what-we-are-going-to-use">What We Are Going to Use</a></p>
</li>
<li><p><a href="#heading-what-you-should-know-before-starting">What You Should Know Before Starting</a></p>
</li>
<li><p><a href="#heading-step-1-create-the-project">Step 1: Create the Project</a></p>
</li>
<li><p><a href="#heading-step-2-create-a-virtual-environment">Step 2: Create a Virtual Environment</a></p>
</li>
<li><p><a href="#heading-step-3-install-the-openai-sdk">Step 3: Install the OpenAI SDK</a></p>
</li>
<li><p><a href="#heading-step-4-create-your-api-key">Step 4: Create Your API Key</a></p>
</li>
<li><p><a href="#heading-step-5-create-requirementstxt">Step 5: Createrequirements.txt</a></p>
</li>
<li><p><a href="#heading-step-6-create-the-python-file">Step 6: Create the Python File</a></p>
</li>
<li><p><a href="#heading-step-7-ask-the-user-for-a-file">Step 7: Ask the User for a File</a></p>
</li>
<li><p><a href="#heading-step-8-check-whether-the-file-exists">Step 8: Check Whether the File Exists</a></p>
</li>
<li><p><a href="#heading-step-9-upload-the-file">Step 9: Upload the File</a></p>
</li>
<li><p><a href="#heading-step-10-look-at-the-uploaded-file-id">Step 10: Look at the Uploaded File ID</a></p>
</li>
<li><p><a href="#heading-step-11-create-the-agents-instructions">Step 11: Create the Agent's Instructions</a></p>
</li>
<li><p><a href="#heading-step-12-ask-the-user-what-they-want-to-know">Step 12: Ask the User What They Want to Know</a></p>
</li>
<li><p><a href="#heading-step-13-send-the-file-and-question-to-the-model">Step 13: Send the File and Question to the Model</a></p>
</li>
<li><p><a href="#heading-step-14-print-the-answer">Step 14: Print the Answer</a></p>
</li>
<li><p><a href="#heading-our-first-complete-version">Our First Complete Version</a></p>
</li>
<li><p><a href="#heading-step-15-run-the-application">Step 15: Run the Application</a></p>
<ul>
<li><a href="#heading-why-is-this-an-agent">Why Is This an Agent?</a></li>
</ul>
</li>
<li><p><a href="#heading-step-16-turn-it-into-a-real-conversation">Step 16: Turn It Into a Real Conversation</a></p>
</li>
<li><p><a href="#heading-step-17-move-the-ai-request-into-the-loop">Step 17: Move the AI Request Into the Loop</a></p>
</li>
<li><p><a href="#heading-step-18-improve-the-agents-instructions">Step 18: Improve the Agent's Instructions</a></p>
<ul>
<li><a href="#heading-why-good-instructions-matter">Why Good Instructions Matter</a></li>
</ul>
</li>
<li><p><a href="#heading-step-19-add-error-handling">Step 19: Add Error Handling</a></p>
</li>
<li><p><a href="#heading-step-20-validate-the-file-extension">Step 20: Validate the File Extension</a></p>
</li>
<li><p><a href="#heading-step-21-add-a-file-name-to-the-interface">Step 21: Add a File Name to the Interface</a></p>
</li>
<li><p><a href="#heading-step-22-build-the-clean-final-version">Step 22: Build the Clean Final Version</a></p>
<ul>
<li><p><a href="#heading-lets-understand-the-architecture">Let's Understand the Architecture</a></p>
</li>
<li><p><a href="#heading-why-we-dont-need-to-manually-extract-every-pdf">Why We Don't Need to Manually Extract Every PDF</a></p>
</li>
<li><p><a href="#heading-but-what-about-very-large-files">But What About Very Large Files?</a></p>
</li>
<li><p><a href="#heading-direct-file-input-vs-rag">Direct File Input vs RAG</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-step-23-make-the-agent-better-at-different-types-of-files">Step 23: Make the Agent Better at Different Types of Files</a></p>
</li>
<li><p><a href="#heading-step-24-give-the-agent-a-specific-role">Step 24: Give the Agent a Specific Role</a></p>
</li>
<li><p><a href="#heading-step-25-add-an-analysis-mode">Step 25: Add an Analysis Mode</a></p>
</li>
<li><p><a href="#heading-step-26-why-this-is-different-from-hard-coding-every-answer">Step 26: Why This Is Different From Hard-Coding Every Answer</a></p>
</li>
<li><p><a href="#heading-step-27-security-matters">Step 27: Security Matters</a></p>
</li>
<li><p><a href="#heading-step-28-be-careful-with-sensitive-files">Step 28: Be Careful With Sensitive Files</a></p>
</li>
<li><p><a href="#heading-common-mistakes-that-developers-make">Common Mistakes that Developers Make</a></p>
</li>
<li><p><a href="#heading-how-the-final-program-works">How the Final Program Works</a></p>
</li>
<li><p><a href="#heading-the-most-important-code-to-remember">The Most Important Code to Remember</a></p>
</li>
<li><p><a href="#heading-what-you-can-build-with-this">What You Can Build With This</a></p>
</li>
<li><p><a href="#heading-final-thoughts">Final Thoughts</a></p>
</li>
</ul>
<h2 id="heading-what-are-we-actually-building">What Are We Actually Building?</h2>
<p>Before writing code, let's define what an AI agent actually means.</p>
<p>An ordinary AI chatbot might work like this:</p>
<pre><code class="language-text">User → Question → AI → Answer
</code></pre>
<p>An AI agent can be more flexible:</p>
<pre><code class="language-text">User → Goal → Agent → Decide what it needs → Use tools/data → Analyze → Answer
</code></pre>
<p>For our project, the “data” will be a file.</p>
<p>For example, imagine we give our agent a research paper called:</p>
<pre><code class="language-text">ai-research.pdf
</code></pre>
<p>Then we ask:</p>
<pre><code class="language-text">What is the main argument of this paper?
</code></pre>
<p>The agent needs to:</p>
<ol>
<li><p>Receive the question.</p>
</li>
<li><p>Access the file.</p>
</li>
<li><p>Read the relevant content.</p>
</li>
<li><p>Understand the content.</p>
</li>
<li><p>Analyze it.</p>
</li>
<li><p>Produce an answer.</p>
</li>
</ol>
<p>The AI model handles the language understanding and reasoning. Our Python program handles the workflow around it.</p>
<p>That distinction is important.</p>
<p>The model isn't magically reading files sitting on your laptop. <strong>Our application has to give the model access to the file.</strong></p>
<p>OpenAI's current API supports sending uploaded files as inputs to the Responses API, which allows models to analyze files directly.</p>
<h2 id="heading-what-we-are-going-to-use">What We Are Going to Use</h2>
<p>Our project will use:</p>
<ul>
<li><p><strong>Python</strong>: our programming language</p>
</li>
<li><p><strong>OpenAI Python SDK</strong>: lets Python communicate with the OpenAI API</p>
</li>
<li><p><strong>Responses API</strong>: the API endpoint we'll use to interact with the model</p>
</li>
<li><p><strong>An uploaded file</strong>: the information our agent will analyze</p>
</li>
<li><p><strong>A prompt</strong>: instructions telling the agent what to do</p>
</li>
</ul>
<p>We'll intentionally keep the first version simple.</p>
<p>You don't need LangChain, a vector database, React, or a complicated backend.</p>
<p>Once you understand this version, you can add those technologies later.</p>
<h2 id="heading-what-you-should-know-before-starting">What You Should Know Before Starting</h2>
<p>This tutorial is designed for beginner and intermediate developers.</p>
<p>You should be comfortable with basic Python concepts such as:</p>
<ul>
<li><p>Variables</p>
</li>
<li><p>Functions</p>
</li>
<li><p><code>if</code> statements</p>
</li>
<li><p>Imports</p>
</li>
<li><p>Strings</p>
</li>
<li><p>Lists</p>
</li>
<li><p>Dictionaries</p>
</li>
<li><p>Running Python programs from a terminal</p>
</li>
</ul>
<p>You do <strong>not</strong> need to know machine learning, know how transformers work internally, or the mathematics behind large language models.</p>
<p>We're focusing on how to build the application here.</p>
<h2 id="heading-step-1-create-the-project">Step 1: Create the Project</h2>
<p>First, create a folder for the project.</p>
<p>For example:</p>
<pre><code class="language-text">file-analysis-agent/
</code></pre>
<p>Inside it, we'll eventually have:</p>
<pre><code class="language-text">file-analysis-agent/
│
├── agent.py
├── requirements.txt
└── .env
</code></pre>
<p>Each file has a purpose.</p>
<ol>
<li><p><code>agent.py</code>: This is where our Python application lives.</p>
</li>
<li><p><code>requirements.txt</code>: This tells Python which external packages our project needs.</p>
</li>
<li><p><code>.env</code>: This is where we can store our API key locally instead of putting it directly into our Python code.</p>
</li>
</ol>
<p>Keeping secrets out of source code is an important habit to develop early.</p>
<h2 id="heading-step-2-create-a-virtual-environment">Step 2: Create a Virtual Environment</h2>
<p>Open your terminal inside the project folder.</p>
<p>Run:</p>
<pre><code class="language-bash">python -m venv venv
</code></pre>
<p>This creates a Python virtual environment.</p>
<p>A virtual environment gives your project its own isolated collection of Python packages. Think of it like giving this project its own little Python workspace.</p>
<p>You can activate it on Windows with:</p>
<pre><code class="language-bash">venv\Scripts\activate
</code></pre>
<p>On macOS or Linux:</p>
<pre><code class="language-bash">source venv/bin/activate
</code></pre>
<p>Once activated, you should see something similar to:</p>
<pre><code class="language-text">(venv)
</code></pre>
<p>at the beginning of your terminal prompt.</p>
<h2 id="heading-step-3-install-the-openai-sdk">Step 3: Install the OpenAI SDK</h2>
<p>Now install the official OpenAI Python package:</p>
<pre><code class="language-bash">pip install openai
</code></pre>
<p>The SDK gives us Python classes and methods that make API calls much easier.</p>
<p>Without an SDK, we would have to manually construct HTTP requests.</p>
<p>With the SDK, we can write Python like:</p>
<pre><code class="language-python">client.responses.create(...)
</code></pre>
<p>instead of manually constructing the entire HTTP request.</p>
<p>The OpenAI quickstart currently uses the Responses API as the starting point for API requests.</p>
<h2 id="heading-step-4-create-your-api-key">Step 4: Create Your API Key</h2>
<p>You need an OpenAI API key to communicate with the API. Create an API key through your OpenAI developer account.</p>
<p>Do <strong>not</strong> put your real API key directly into your source code like this:</p>
<pre><code class="language-python">api_key = "sk-your-real-key"
</code></pre>
<p>That's a bad habit.</p>
<p>If you upload your project to GitHub, you could accidentally expose the key. Instead, store it as an environment variable.</p>
<p>For example, on Windows PowerShell:</p>
<pre><code class="language-powershell">$env:OPENAI_API_KEY="your_api_key_here"
</code></pre>
<p>On macOS/Linux:</p>
<pre><code class="language-bash">export OPENAI_API_KEY="your_api_key_here"
</code></pre>
<p>The OpenAI SDK can automatically read the <code>OPENAI_API_KEY</code> environment variable.</p>
<h2 id="heading-step-5-create-requirementstxt">Step 5: Create <code>requirements.txt</code></h2>
<p>Create a file called:</p>
<pre><code class="language-text">requirements.txt
</code></pre>
<p>Put this inside:</p>
<pre><code class="language-text">openai
</code></pre>
<p>Now another developer can install the project's dependency with:</p>
<pre><code class="language-bash">pip install -r requirements.txt
</code></pre>
<p>This is a small thing, but it's a very useful professional habit.</p>
<h2 id="heading-step-6-create-the-python-file">Step 6: Create the Python File</h2>
<p>Create:</p>
<pre><code class="language-text">agent.py
</code></pre>
<p>Start with:</p>
<pre><code class="language-python">from openai import OpenAI
</code></pre>
<p>Let's break this down.</p>
<ul>
<li><p><code>from</code>: Python's <code>from</code> keyword allows us to import something from another module.</p>
</li>
<li><p><code>openai</code>: This is the Python package we installed.</p>
</li>
<li><p><code>import OpenAI</code>: We're importing the <code>OpenAI</code> class from that package.</p>
</li>
</ul>
<p>Now we can create an OpenAI client.</p>
<p>Add:</p>
<pre><code class="language-python">client = OpenAI()
</code></pre>
<p>This creates our API client.</p>
<p>You can think of <code>client</code> as our application's connection point to the OpenAI API. Whenever we want to communicate with the API, we'll use this client.</p>
<p>For example:</p>
<pre><code class="language-python">response = client.responses.create(...)
</code></pre>
<p>The client handles the underlying HTTP communication for us.</p>
<h2 id="heading-step-7-ask-the-user-for-a-file">Step 7: Ask the User for a File</h2>
<p>We want our application to allow the user to specify a file.</p>
<p>Add:</p>
<pre><code class="language-python">file_path = input("Enter the path to your file: ")
</code></pre>
<p>Now let's understand this line.</p>
<p>The <code>input()</code> function waits for the user to type something.</p>
<p>For example, the terminal might display:</p>
<pre><code class="language-text">Enter the path to your file:
</code></pre>
<p>The user might type:</p>
<pre><code class="language-text">research.pdf
</code></pre>
<p>Python stores that text inside:</p>
<pre><code class="language-python">file_path
</code></pre>
<p>So after the user enters:</p>
<pre><code class="language-text">research.pdf
</code></pre>
<p>we effectively have:</p>
<pre><code class="language-python">file_path = "research.pdf"
</code></pre>
<p>Now our program knows which file the user wants to analyze.</p>
<h2 id="heading-step-8-check-whether-the-file-exists">Step 8: Check Whether the File Exists</h2>
<p>Before uploading anything, it's a good idea to make sure the file actually exists.</p>
<p>We can use Python's built-in <code>os</code> module for this.</p>
<p>Add:</p>
<pre><code class="language-python">import os
</code></pre>
<p>Then:</p>
<pre><code class="language-python">if not os.path.exists(file_path):
print("File not found.")
exit()
</code></pre>
<p>Let's break this down.</p>
<p>The <code>os</code> module gives Python tools for interacting with the operating system.</p>
<p>One of those tools is:</p>
<pre><code class="language-python">os.path.exists()
</code></pre>
<p>It checks whether a file or folder exists at a particular path.</p>
<p><code>if</code>: We're checking a condition.</p>
<pre><code class="language-python">if not os.path.exists(file_path):
</code></pre>
<p>This means:</p>
<blockquote>
<p>If the file does NOT exist...</p>
</blockquote>
<p>The <code>not</code> keyword reverses the result.</p>
<p>If:</p>
<pre><code class="language-python">os.path.exists(file_path)
</code></pre>
<p>returns <code>True</code> then <code>not True</code> becomes <code>False</code>. But if the file doesn't exist...<code>False</code> becomes <code>True</code>.</p>
<p>So the code inside the <code>if</code> statement only runs when the file can't be found.</p>
<p>Next, <code>print()</code> displays:</p>
<pre><code class="language-text">File not found.
</code></pre>
<p><code>exit()</code> stops the program.</p>
<p>That prevents our application from trying to upload a file that doesn't exist.</p>
<h2 id="heading-step-9-upload-the-file">Step 9: Upload the File</h2>
<p>Now comes the interesting part: we need to send the file to the API.</p>
<p>Add:</p>
<pre><code class="language-python">with open(file_path, "rb") as file:
uploaded_file = client.files.create(
file=file,
purpose="user_data"
)
</code></pre>
<p>This looks more complicated than it really is.</p>
<p>Let's go through it piece by piece.</p>
<h3 id="heading-understanding-open">Understanding <code>open()</code></h3>
<p>The first line is:</p>
<pre><code class="language-python">with open(file_path, "rb") as file:
</code></pre>
<p>The <code>open()</code> function opens a file.</p>
<p>The first argument is:</p>
<pre><code class="language-python">file_path
</code></pre>
<p>which is the path entered by the user.</p>
<p>The second argument is:</p>
<pre><code class="language-python">"rb"
</code></pre>
<p>This means:</p>
<ul>
<li><p><code>r</code> = read</p>
</li>
<li><p><code>b</code> = binary</p>
</li>
</ul>
<p>We use binary mode because we're dealing with uploaded files rather than simply reading plain text.</p>
<p>The <code>with</code> statement is important because Python automatically handles closing the file when we are finished with it.</p>
<p>The variable:</p>
<pre><code class="language-python">file
</code></pre>
<p>represents the opened file.</p>
<h3 id="heading-uploading-the-file">Uploading the File</h3>
<p>Inside the <code>with</code> block we have:</p>
<pre><code class="language-python">uploaded_file = client.files.create(
</code></pre>
<p>This asks the OpenAI API to create an uploaded file.</p>
<p>The <code>file</code> argument:</p>
<pre><code class="language-python">file=file
</code></pre>
<p>passes the file we opened.</p>
<p>Then:</p>
<pre><code class="language-python">purpose="user_data"
</code></pre>
<p>tells the API that the uploaded file is intended to be used as user data.</p>
<p>The Files API supports a <code>user_data</code> purpose for flexible file use.</p>
<p>After this finishes, OpenAI returns information about the uploaded file. We store that information in:</p>
<pre><code class="language-python">uploaded_file
</code></pre>
<p>One useful property is:</p>
<pre><code class="language-python">uploaded_file.id
</code></pre>
<p>That ID identifies the uploaded file.</p>
<h2 id="heading-step-10-look-at-the-uploaded-file-id">Step 10: Look at the Uploaded File ID</h2>
<p>Add:</p>
<pre><code class="language-python">print("Uploaded file:", uploaded_file.id)
</code></pre>
<p>Now you can see something like:</p>
<pre><code class="language-text">Uploaded file: file-abc123
</code></pre>
<p>That ID is important.</p>
<p>Our local computer knows the file as:</p>
<pre><code class="language-text">research.pdf
</code></pre>
<p>The API knows it through something like:</p>
<pre><code class="language-text">file-abc123
</code></pre>
<p>We can use that ID when sending the file to the model.</p>
<h2 id="heading-step-11-create-the-agents-instructions">Step 11: Create the Agent's Instructions</h2>
<p>Now we need to tell the AI what its job is.</p>
<p>Create:</p>
<pre><code class="language-python">instructions = """
You are a file analysis assistant.
Your job is to carefully analyze the file provided by the user.
Answer questions using information from the file.
If the answer can't be found in the file, clearly say that the information is not available in the file.
Do not invent facts.
When useful, organize your answer with headings and bullet points.
"""
</code></pre>
<p>This is called an instruction or prompt.</p>
<p>The triple quotes:</p>
<pre><code class="language-python">"""
...
"""
</code></pre>
<p>allow us to create a multi-line string.</p>
<p>Our agent now has a role.</p>
<p>It knows:</p>
<ul>
<li><p>What it's supposed to do</p>
</li>
<li><p>What information it should use</p>
</li>
<li><p>What to do when information is missing</p>
</li>
<li><p>How it should format answers</p>
</li>
</ul>
<p>The instruction:</p>
<pre><code class="language-text">Do not invent facts.
</code></pre>
<p>is especially important for file-analysis applications.</p>
<p>We want the model to distinguish between:</p>
<blockquote>
<p>“The file says this.”</p>
</blockquote>
<p>and:</p>
<blockquote>
<p>“I think this might be true.”</p>
</blockquote>
<p>Those are not the same thing.</p>
<h2 id="heading-step-12-ask-the-user-what-they-want-to-know">Step 12: Ask the User What They Want to Know</h2>
<p>Now we need the actual question.</p>
<p>Add:</p>
<pre><code class="language-python">question = input("What would you like me to analyze? ")
</code></pre>
<p>For example, the user could enter:</p>
<pre><code class="language-text">What are the three most important findings in this paper?
</code></pre>
<p>Or:</p>
<pre><code class="language-text">Summarize this document in five bullet points.
</code></pre>
<p>Or:</p>
<pre><code class="language-text">What methodology did the researchers use?
</code></pre>
<p>This is where our application becomes flexible.</p>
<p>We don't need to create separate Python functions for every possible question. The user can ask questions naturally.</p>
<h2 id="heading-step-13-send-the-file-and-question-to-the-model">Step 13: Send the File and Question to the Model</h2>
<p>Now we can finally create the response.</p>
<p>Add:</p>
<pre><code class="language-python">response = client.responses.create(
model="gpt-5",
instructions=instructions,
input=[
{
"role": "user",
"content": [
{
"type": "input_text",
"text": question
},
{
"type": "input_file",
"file_id": uploaded_file.id
}
]
}
]
)
</code></pre>
<p>This is the most important section of the entire project.</p>
<p>Let's slow down and understand it.</p>
<h3 id="heading-understanding-clientresponsescreate">Understanding <code>client.responses.create()</code></h3>
<p>We start with:</p>
<pre><code class="language-python">client.responses.create(
</code></pre>
<p>We're asking the Responses API to generate a response.</p>
<p>The OpenAI API supports file inputs in the Responses API, including using an uploaded file's ID as an <code>input_file</code>.</p>
<h3 id="heading-understanding-the-model">Understanding the Model</h3>
<p>We have:</p>
<pre><code class="language-python">model="gpt-5"
</code></pre>
<p>This tells the API which model should process the request.</p>
<p>The model is the part responsible for understanding the question and analyzing the information provided to it.</p>
<p>The exact model you choose can change over time, so treat the model name as a configurable part of your application rather than something permanently hard-coded into your architecture.</p>
<h3 id="heading-understanding-instructions">Understanding <code>instructions</code></h3>
<p>Next:</p>
<pre><code class="language-python">instructions=instructions
</code></pre>
<p>Remember the variable we created earlier?</p>
<pre><code class="language-python">instructions = """
You are a file analysis assistant.
...
"""
</code></pre>
<p>We're passing those instructions into the API request so the model knows what role it should perform.</p>
<h3 id="heading-understanding-input">Understanding <code>input</code></h3>
<p>Next we have:</p>
<pre><code class="language-python">input=[
</code></pre>
<p>The <code>input</code> contains the information we give the model.</p>
<p>In our case, we're giving it:</p>
<ol>
<li><p>The user's question</p>
</li>
<li><p>The file</p>
</li>
</ol>
<p>This is important because an AI model can't answer a file-specific question if we never give it the file.</p>
<h3 id="heading-understanding-the-user-message">Understanding the User Message</h3>
<p>Inside the input we have:</p>
<pre><code class="language-python">{
"role": "user",
</code></pre>
<p>This tells the API that this input represents the user's message.</p>
<p>Then:</p>
<pre><code class="language-python">"content": [
</code></pre>
<p>contains the actual content of that message.</p>
<h3 id="heading-sending-the-question">Sending the Question</h3>
<p>The first content item is:</p>
<pre><code class="language-python">{
"type": "input_text",
"text": question
}
</code></pre>
<p>This tells the model:</p>
<blockquote>
<p>Here is some text input.</p>
</blockquote>
<p>The actual text comes from:</p>
<pre><code class="language-python">question
</code></pre>
<p>which was entered by the user.</p>
<p>If the user entered:</p>
<pre><code class="language-text">What is the main conclusion?
</code></pre>
<p>then the model receives that question.</p>
<h3 id="heading-sending-the-file">Sending the File</h3>
<p>The next content item is:</p>
<pre><code class="language-python">{
"type": "input_file",
"file_id": uploaded_file.id
}
</code></pre>
<p>This tells the API:</p>
<blockquote>
<p>Here is a file input.</p>
</blockquote>
<p>And:</p>
<pre><code class="language-python">uploaded_file.id
</code></pre>
<p>tells the API exactly which uploaded file we're referring to.</p>
<p>So our request effectively contains:</p>
<pre><code class="language-text">Question:
"What is the main conclusion?"
File:
research.pdf
</code></pre>
<p>The model can then analyze the provided file in the context of the user's question.</p>
<h2 id="heading-step-14-print-the-answer">Step 14: Print the Answer</h2>
<p>We have the response stored in:</p>
<pre><code class="language-python">response
</code></pre>
<p>But we don't want to print the entire response object.</p>
<p>We want the generated text.</p>
<p>The SDK provides:</p>
<pre><code class="language-python">response.output_text
</code></pre>
<p>So add:</p>
<pre><code class="language-python">print("\nAgent:\n")
print(response.output_text)
</code></pre>
<p>The first <code>print()</code> creates a little spacing and prints:</p>
<pre><code class="language-text">Agent:
</code></pre>
<p>The second prints the actual answer.</p>
<h2 id="heading-our-first-complete-version">Our First Complete Version</h2>
<p>At this point, our entire <code>agent.py</code> looks like this:</p>
<pre><code class="language-python">import os
from openai import OpenAI
client = OpenAI()
file_path = input("Enter the path to your file: ")
if not os.path.exists(file_path):
print("File not found.")
exit()
with open(file_path, "rb") as file:
uploaded_file = client.files.create(
file=file,
purpose="user_data"
)
print("Uploaded file:", uploaded_file.id)
instructions = """
You are a file analysis assistant.
Your job is to carefully analyze the file provided by the user.
Answer questions using information from the file.
If the answer cannot be found in the file, clearly say that the information is not available in the file.
Do not invent facts.
When useful, organize your answer with headings and bullet points.
"""
question = input("What would you like me to analyze? ")
response = client.responses.create(
model="gpt-5",
instructions=instructions,
input=[
{
"role": "user",
"content": [
{
"type": "input_text",
"text": question
},
{
"type": "input_file",
"file_id": uploaded_file.id
}
]
}
]
)
print("\nAgent:\n")
print(response.output_text)
</code></pre>
<p>That's already a functional file-analysis AI application.</p>
<p>But we can make it much better.</p>
<h2 id="heading-step-15-run-the-application">Step 15: Run the Application</h2>
<p>Place a file such as:</p>
<pre><code class="language-text">research.pdf
</code></pre>
<p>inside your project folder.</p>
<p>Then run:</p>
<pre><code class="language-bash">python agent.py
</code></pre>
<p>You should see:</p>
<pre><code class="language-text">Enter the path to your file:
</code></pre>
<p>Enter:</p>
<pre><code class="language-text">research.pdf
</code></pre>
<p>Then you might see:</p>
<pre><code class="language-text">Uploaded file: file-abc123
</code></pre>
<p>Next:</p>
<pre><code class="language-text">What would you like me to analyze?
</code></pre>
<p>You could ask:</p>
<pre><code class="language-text">Summarize the main findings in five bullet points.
</code></pre>
<p>The agent will analyze the file and return an answer.</p>
<h3 id="heading-why-is-this-an-agent">Why Is This an Agent?</h3>
<p>At first glance, this might look like a normal API call. And technically, yes, our first version is a fairly simple agent workflow.</p>
<p>The important concept is the <strong>agent loop</strong>.</p>
<p>An agent generally has:</p>
<ol>
<li><p>A goal</p>
</li>
<li><p>Instructions</p>
</li>
<li><p>Access to information</p>
</li>
<li><p>Potential tools</p>
</li>
<li><p>A reasoning process</p>
</li>
<li><p>An action</p>
</li>
<li><p>An output</p>
</li>
</ol>
<p>Our application has several of these pieces.</p>
<p>The user provides a goal:</p>
<pre><code class="language-text">Analyze this research paper.
</code></pre>
<p>The instructions define the agent's behavior:</p>
<pre><code class="language-text">You are a file analysis assistant.
</code></pre>
<p>The file provides information:</p>
<pre><code class="language-text">research.pdf
</code></pre>
<p>The model processes the information, then the application returns the result.</p>
<p>As applications become more advanced, agents can also use tools such as file search, web search, function calling, and other external systems. OpenAI's platform currently supports built-in tools and custom function tools for extending agents.</p>
<h2 id="heading-step-16-turn-it-into-a-real-conversation">Step 16: Turn It Into a Real Conversation</h2>
<p>Our current application only asks one question.</p>
<p>That's useful, but not ideal.</p>
<p>Imagine uploading a research paper and then having to restart the program every time you want to ask another question.</p>
<p>We can improve that by putting the question inside a loop.</p>
<p>Instead of:</p>
<pre><code class="language-python">question = input("What would you like me to analyze? ")
</code></pre>
<p>we can use:</p>
<pre><code class="language-python">while True:
question = input("\nAsk a question (or type 'exit'): ")
if question.lower() == "exit":
break
</code></pre>
<p>Now let's understand it.</p>
<ul>
<li><p><code>while True</code>: This creates a loop that continues indefinitely. It will keep asking questions until we tell it to stop.</p>
</li>
<li><p><code>question = input(...)</code>: The user enters another question.</p>
</li>
<li><p><code>question.lower()</code>: The <code>.lower()</code> method converts the question to lowercase.</p>
</li>
</ul>
<p>For example:</p>
<pre><code class="language-text">EXIT
</code></pre>
<p>becomes:</p>
<pre><code class="language-text">exit
</code></pre>
<p>and:</p>
<pre><code class="language-text">Exit
</code></pre>
<p>also becomes:</p>
<pre><code class="language-text">exit
</code></pre>
<p>This makes our exit check more reliable.</p>
<p>Finally, the <code>break</code> keyword stops the loop. So:</p>
<pre><code class="language-python">if question.lower() == "exit":
break
</code></pre>
<p>means:</p>
<blockquote>
<p>If the user types exit, stop asking questions.</p>
</blockquote>
<h2 id="heading-step-17-move-the-ai-request-into-the-loop">Step 17: Move the AI Request Into the Loop</h2>
<p>Now the API request needs to happen inside the loop.</p>
<p>Our structure becomes:</p>
<pre><code class="language-python">while True:
question = input("\nAsk a question (or type 'exit'): ")
if question.lower() == "exit":
break
response = client.responses.create(
model="gpt-5",
instructions=instructions,
input=[
{
"role": "user",
"content": [
{
"type": "input_text",
"text": question
},
{
"type": "input_file",
"file_id": uploaded_file.id
}
]
}
]
)
print("\nAgent:\n")
print(response.output_text)
</code></pre>
<p>Now the user can ask multiple questions about the same file.</p>
<p>For example:</p>
<pre><code class="language-text">Ask a question:
What is this paper about?
</code></pre>
<p>Then:</p>
<pre><code class="language-text">Ask a question:
What methodology did the researchers use?
</code></pre>
<p>Then:</p>
<pre><code class="language-text">Ask a question:
What were the biggest limitations?
</code></pre>
<p>And finally:</p>
<pre><code class="language-text">Ask a question:
exit
</code></pre>
<p>This makes the application feel much more like an actual assistant.</p>
<h2 id="heading-step-18-improve-the-agents-instructions">Step 18: Improve the Agent's Instructions</h2>
<p>A good AI application isn't just about calling an API. The instructions matter a lot.</p>
<p>We can make our instructions more specific.</p>
<p>For example:</p>
<pre><code class="language-python">instructions = """
You are an AI file analysis assistant.
Your job is to analyze the file provided by the user.
Follow these rules:
1. Use the provided file as your primary source.
2. Answer the user's question directly.
3. Do not invent information that is not supported by the file.
4. If the file does not contain enough information to answer a question, say so.
5. When summarizing, focus on the most important information.
6. When comparing ideas, clearly explain the similarities and differences.
7. When analyzing research, distinguish between results, methods, and conclusions.
8. Use simple language unless the user asks for technical language.
9. Use bullet points when they make the answer easier to understand.
10. If you make an inference, clearly label it as an inference.
"""
</code></pre>
<p>This is much stronger.</p>
<p>We're essentially giving our AI a set of rules.</p>
<h3 id="heading-why-good-instructions-matter">Why Good Instructions Matter</h3>
<p>Imagine telling someone:</p>
<blockquote>
<p>“Read this document.”</p>
</blockquote>
<p>They might read it and give you almost anything.</p>
<p>Now imagine saying:</p>
<blockquote>
<p>“Read this document, identify the research question, summarize the methodology, identify the major findings, and explain the limitations using simple language.”</p>
</blockquote>
<p>That second instruction is much more useful.</p>
<p>AI agents work the same way. The more clearly you define the job, the easier it is for the model to produce consistent results.</p>
<h2 id="heading-step-19-add-error-handling">Step 19: Add Error Handling</h2>
<p>Right now, our program assumes everything will work.</p>
<p>Real applications shouldn't do that. Files can fail to upload, the API can return an error, the user can enter an invalid path, or the network can temporarily fail.</p>
<p>We can use <code>try</code> and <code>except</code> to handle these situations.</p>
<p>For example:</p>
<pre><code class="language-python">try:
response = client.responses.create(
model="gpt-5",
instructions=instructions,
input=[
{
"role": "user",
"content": [
{
"type": "input_text",
"text": question
},
{
"type": "input_file",
"file_id": uploaded_file.id
}
]
}
]
)
print(response.output_text)
except Exception as error:
print("Something went wrong:")
print(error)
</code></pre>
<ul>
<li><p><code>try</code>: The code inside the <code>try</code> block is code that might fail.</p>
</li>
<li><p><code>except</code>: If an error happens, Python jumps to the <code>except</code> block.</p>
</li>
<li><p><code>Exception as error</code>: This captures the error so we can display it.</p>
</li>
</ul>
<p>Instead of the entire application crashing with a confusing traceback, the user sees:</p>
<pre><code class="language-text">Something went wrong:
...
</code></pre>
<p>For a production application, you would usually want more sophisticated logging and error handling, but this is a good starting point.</p>
<h2 id="heading-step-20-validate-the-file-extension">Step 20: Validate the File Extension</h2>
<p>We can also check which type of file the user selected.</p>
<p>Add:</p>
<pre><code class="language-python">allowed_extensions = {
".pdf",
".txt",
".docx",
".csv"
}
</code></pre>
<p>This creates a set of file extensions that our application expects to support.</p>
<p>Then:</p>
<pre><code class="language-python">extension = os.path.splitext(file_path)[1].lower()
</code></pre>
<p>Let's break this down.</p>
<h3 id="heading-ospathsplitext"><code>os.path.splitext()</code></h3>
<p>This separates the filename from its extension.</p>
<p>For:</p>
<pre><code class="language-text">research.pdf
</code></pre>
<p>it gives us approximately:</p>
<pre><code class="language-text">research
</code></pre>
<p>and:</p>
<pre><code class="language-text">.pdf
</code></pre>
<p>The <code>[1]</code> selects the extension.</p>
<p>Then:</p>
<pre><code class="language-python">.lower()
</code></pre>
<p>converts it to lowercase.</p>
<p>So:</p>
<pre><code class="language-text">RESEARCH.PDF
</code></pre>
<p>becomes:</p>
<pre><code class="language-text">.pdf
</code></pre>
<p>Now we can check:</p>
<pre><code class="language-python">if extension not in allowed_extensions:
print("Unsupported file type.")
exit()
</code></pre>
<p>This prevents users from uploading file types our application hasn't been designed to handle.</p>
<p>Always verify the currently supported file types for the API and model you choose before expanding your application. OpenAI's file and input APIs document file handling and supported input types.</p>
<h2 id="heading-step-21-add-a-file-name-to-the-interface">Step 21: Add a File Name to the Interface</h2>
<p>We can make the terminal experience slightly nicer.</p>
<p>Instead of:</p>
<pre><code class="language-python">print("Uploaded file:", uploaded_file.id)
</code></pre>
<p>we can write:</p>
<pre><code class="language-python">print(f"\nSuccessfully uploaded: {os.path.basename(file_path)}")
</code></pre>
<p>The <code>f</code> before the string creates an f-string.</p>
<p>That allows us to insert Python variables inside <code>{}</code>.</p>
<p>For example:</p>
<pre><code class="language-python">f"Successfully uploaded: {os.path.basename(file_path)}"
</code></pre>
<p>might produce:</p>
<pre><code class="language-text">Successfully uploaded: research.pdf
</code></pre>
<h3 id="heading-ospathbasename"><code>os.path.basename()</code></h3>
<p>This extracts just the filename from the path.</p>
<p>If the user enters:</p>
<pre><code class="language-text">documents/research.pdf
</code></pre>
<p>then:</p>
<pre><code class="language-python">os.path.basename(file_path)
</code></pre>
<p>returns:</p>
<pre><code class="language-text">research.pdf
</code></pre>
<h2 id="heading-step-22-build-the-clean-final-version">Step 22: Build the Clean Final Version</h2>
<p>Now let's combine everything.</p>
<p>Here is a cleaner version of our application:</p>
<pre><code class="language-python">import os
from openai import OpenAI
# Create the OpenAI client.
client = OpenAI()
# Ask the user for a file.
file_path = input("Enter the path to your file: ").strip()
# Make sure the file exists.
if not os.path.exists(file_path):
print("File not found.")
exit()
# Allowed file types.
allowed_extensions = {
".pdf",
".txt",
".docx",
".csv"
}
# Get the file extension.
extension = os.path.splitext(file_path)[1].lower()
# Make sure the file type is supported by our application.
if extension not in allowed_extensions:
print(f"Unsupported file type: {extension}")
print("Supported types:", ", ".join(allowed_extensions))
exit()
# Upload the file.
try:
with open(file_path, "rb") as file:
uploaded_file = client.files.create(
file=file,
purpose="user_data"
)
except Exception as error:
print("The file could not be uploaded.")
print(error)
exit()
print(f"\nSuccessfully uploaded: {os.path.basename(file_path)}")
# Define the agent's behavior.
instructions = """
You are an AI file analysis assistant.
Your job is to analyze the file provided by the user.
Follow these rules:
1. Use the provided file as your primary source.
2. Answer the user's question directly.
3. Do not invent information that is not supported by the file.
4. If the file does not contain enough information to answer a question, say so.
5. When summarizing, focus on the most important information.
6. When comparing ideas, clearly explain similarities and differences.
7. When analyzing research, distinguish between methods, results, and conclusions.
8. Use simple language unless the user asks for technical language.
9. Use bullet points when they make the answer easier to understand.
10. If you make an inference, clearly label it as an inference.
"""
# Start the conversation.
print("\nYour file is ready to analyze.")
print("Ask questions about the file.")
print("Type 'exit' when you are finished.")
while True:
# Get a question from the user.
question = input("\nYou: ").strip()
# Stop the program if the user wants to exit.
if question.lower() == "exit":
print("Goodbye!")
break
# Ignore empty questions.
if not question:
print("Please enter a question.")
continue
# Send the question and file to the model.
try:
response = client.responses.create(
model="gpt-5",
instructions=instructions,
input=[
{
"role": "user",
"content": [
{
"type": "input_text",
"text": question
},
{
"type": "input_file",
"file_id": uploaded_file.id
}
]
}
]
)
# Display the AI's response.
print("\nAgent:")
print(response.output_text)
except Exception as error:
print("\nThe agent encountered an error.")
print(error)
</code></pre>
<h3 id="heading-lets-understand-the-architecture">Let's Understand the Architecture</h3>
<p>At this point, it is useful to step away from the code. Our application has several layers.</p>
<h4 id="heading-layer-1-user-interface">Layer 1: User Interface</h4>
<p>The terminal asks:</p>
<pre><code class="language-text">Enter the path to your file:
</code></pre>
<p>and:</p>
<pre><code class="language-text">You:
</code></pre>
<p>This is how the user interacts with our application.</p>
<h4 id="heading-layer-2-file-handling">Layer 2: File Handling</h4>
<p>Python checks:</p>
<pre><code class="language-python">os.path.exists(file_path)
</code></pre>
<p>and opens:</p>
<pre><code class="language-python">open(file_path, "rb")
</code></pre>
<p>This layer handles the local file.</p>
<h4 id="heading-layer-3-file-upload">Layer 3: File Upload</h4>
<p>The application sends the file to the API:</p>
<pre><code class="language-python">client.files.create(...)
</code></pre>
<p>The API gives us a file ID.</p>
<h4 id="heading-layer-4-agent-instructions">Layer 4: Agent Instructions</h4>
<p>We define:</p>
<pre><code class="language-python">instructions
</code></pre>
<p>This tells the model how to behave.</p>
<h4 id="heading-layer-5-user-request">Layer 5: User Request</h4>
<p>The user asks:</p>
<pre><code class="language-text">What are the main findings?
</code></pre>
<h4 id="heading-layer-6-model">Layer 6: Model</h4>
<p>The model receives:</p>
<ul>
<li><p>The instructions</p>
</li>
<li><p>The question</p>
</li>
<li><p>The file</p>
</li>
</ul>
<p>and generates an answer.</p>
<h4 id="heading-layer-7-output">Layer 7: Output</h4>
<p>We display:</p>
<pre><code class="language-python">response.output_text
</code></pre>
<p>to the user.</p>
<p>This separation is useful because it makes the project easier to extend later.</p>
<h3 id="heading-why-we-dont-need-to-manually-extract-every-pdf">Why We Don't Need to Manually Extract Every PDF</h3>
<p>A beginner might wonder:</p>
<blockquote>
<p>“Why don't we use Python to extract all the text first?”</p>
</blockquote>
<p>That's absolutely possible. You could use libraries such as:</p>
<pre><code class="language-text">PyPDF
python-docx
pandas
</code></pre>
<p>to read different file formats yourself.</p>
<p>Then you could send the extracted text to an AI model.</p>
<p>That approach can be useful, especially when you need custom preprocessing. But it also creates more work.</p>
<p>You would need to write separate logic for:</p>
<pre><code class="language-text">PDF → extract text
DOCX → extract text
CSV → read rows
TXT → read text
</code></pre>
<p>Then you would need to figure out how to send all that information to the model.</p>
<p>With file inputs, the API can accept the file directly, which can simplify the architecture for supported use cases.</p>
<h3 id="heading-but-what-about-very-large-files">But What About Very Large Files?</h3>
<p>This is where things get more interesting.</p>
<p>Imagine a user uploads a 2,000-page collection of documents. You probably don't want to send everything into every single request.</p>
<p>Instead, you may want a system that can search for the most relevant sections. This is where <strong>retrieval</strong> becomes important.</p>
<p>One common architecture is:</p>
<pre><code class="language-text">Documents
↓
Split into chunks
↓
Create embeddings
↓
Store searchable representations
↓
User asks question
↓
Find relevant chunks
↓
Send relevant information to model
↓
Generate answer
</code></pre>
<p>This approach is commonly associated with <strong>Retrieval-Augmented Generation</strong>, or RAG.</p>
<p>OpenAI also provides a file search tool that can search uploaded files using vector stores.</p>
<p>Our first project intentionally doesn't introduce RAG because it would add a lot of concepts at once.</p>
<p>First understand direct file analysis. Then learn retrieval. Then combine the two.</p>
<h3 id="heading-direct-file-input-vs-rag">Direct File Input vs RAG</h3>
<p>It's useful to understand the difference.</p>
<h4 id="heading-direct-file-input">Direct File Input</h4>
<p>You give the model a file for a particular request.</p>
<p>For example:</p>
<pre><code class="language-text">Upload:
research-paper.pdf
Question:
What was the main conclusion?
</code></pre>
<p>This is simple and great for many smaller applications.</p>
<h4 id="heading-rag">RAG</h4>
<p>You have a larger collection of documents.</p>
<p>For example:</p>
<pre><code class="language-text">100 research papers
50 reports
20 manuals
</code></pre>
<p>Instead of giving the model every document for every question, you search the collection for relevant information first. Then you provide the relevant pieces to the model.</p>
<p>This is more scalable for large knowledge bases.</p>
<h2 id="heading-step-23-make-the-agent-better-at-different-types-of-files">Step 23: Make the Agent Better at Different Types of Files</h2>
<p>Different files contain different kinds of information.</p>
<p>A PDF might contain:</p>
<pre><code class="language-text">Research paper
</code></pre>
<p>A CSV might contain:</p>
<pre><code class="language-text">Name,Age,Score
Alex,17,91
Sam,18,87
</code></pre>
<p>A DOCX might contain:</p>
<pre><code class="language-text">A long essay
</code></pre>
<p>A good agent should understand what kind of information it is dealing with.</p>
<p>We can make our instructions reflect this.</p>
<p>For example:</p>
<pre><code class="language-python">instructions = """
You are an AI file analysis assistant.
First understand what type of information the uploaded file contains.
If the file is a research paper:
- Identify the research question.
- Explain the methodology.
- Summarize the results.
- Explain the conclusion.
- Identify limitations.
If the file contains tabular data:
- Identify the columns.
- Describe important patterns.
- Identify unusual values when possible.
- Explain trends clearly.
- Do not invent numerical results.
If the file is a general document:
- Identify its main purpose.
- Summarize the important sections.
- Answer questions using information from the document.
Always:
- Use the file as your primary source.
- Do not invent facts.
- Clearly distinguish facts from inferences.
- Say when the file does not contain enough information.
- Use simple language.
"""
</code></pre>
<p>Now our agent has more context about the kinds of work it may perform.</p>
<h2 id="heading-step-24-give-the-agent-a-specific-role">Step 24: Give the Agent a Specific Role</h2>
<p>You can think of the instruction as the agent's job description.</p>
<p>For example:</p>
<pre><code class="language-text">You are an AI research assistant.
</code></pre>
<p>is fairly broad.</p>
<p>But:</p>
<pre><code class="language-text">You are an AI research assistant who analyzes academic papers.
</code></pre>
<p>is more specific.</p>
<p>We can go further:</p>
<pre><code class="language-text">You are an AI research assistant specializing in helping students understand academic papers.
</code></pre>
<p>Now we have a target audience.</p>
<p>The model can adjust its explanations accordingly.</p>
<p>This is one of the easiest ways to make an AI application feel much more useful without writing a huge amount of code.</p>
<h2 id="heading-step-25-add-an-analysis-mode">Step 25: Add an Analysis Mode</h2>
<p>We can make the application even more useful by letting the user select an analysis mode.</p>
<p>For example:</p>
<pre><code class="language-text">1. Summarize
2. Explain
3. Find key points
4. Analyze
5. Ask a question
</code></pre>
<p>We could ask:</p>
<pre><code class="language-python">mode = input(
"\nChoose a mode: "
"summarize, explain, analyze, or question: "
)
</code></pre>
<p>Then modify the prompt based on the user's selection.</p>
<p>For example:</p>
<pre><code class="language-python">if mode.lower() == "summarize":
task = "Summarize the most important information from the file."
elif mode.lower() == "explain":
task = "Explain the file in beginner-friendly language."
elif mode.lower() == "analyze":
task = "Perform a detailed analysis of the file."
else:
task = question
</code></pre>
<p>This is a simple example of application logic controlling an AI model.</p>
<p>The AI still generates the language, but our Python application decides what kind of task it should perform.</p>
<h2 id="heading-step-26-why-this-is-different-from-hard-coding-every-answer">Step 26: Why This Is Different From Hard-Coding Every Answer</h2>
<p>Imagine you wanted to support these questions:</p>
<ol>
<li><p>Summarize the file.</p>
</li>
<li><p>What is the main idea?</p>
</li>
<li><p>What are the limitations?</p>
</li>
<li><p>Who is the target audience?</p>
</li>
<li><p>What evidence supports the conclusion?</p>
</li>
</ol>
<p>You could technically create a separate Python function for each one. But that would quickly become ridiculous.</p>
<p>Instead, we can let the user ask naturally:</p>
<pre><code class="language-python">question = input("What would you like to know? ")
</code></pre>
<p>The AI handles the language. Our application provides the file and context.</p>
<p>This is one of the major advantages of using language models in applications.</p>
<h2 id="heading-step-27-security-matters">Step 27: Security Matters</h2>
<p>Now let's talk about something that's not as exciting as the AI part but is extremely important.</p>
<p><strong>Never expose your API key.</strong></p>
<p>Bad:</p>
<pre><code class="language-python">client = OpenAI(
api_key="sk-real-secret-key"
)
</code></pre>
<p>Better:</p>
<pre><code class="language-python">client = OpenAI()
</code></pre>
<p>with the key stored in an environment variable.</p>
<p>Also avoid committing secrets to GitHub.</p>
<p>Your <code>.gitignore</code> file should include things such as:</p>
<pre><code class="language-text">.env
venv/
__pycache__/
</code></pre>
<p>If you decide to use a <code>.env</code> file locally, make sure it is ignored by Git.</p>
<h2 id="heading-step-28-be-careful-with-sensitive-files">Step 28: Be Careful With Sensitive Files</h2>
<p>A file-analysis agent can potentially process sensitive information.</p>
<p>That means you should think carefully before uploading things such as:</p>
<ul>
<li><p>Medical records</p>
</li>
<li><p>Financial information</p>
</li>
<li><p>Passwords</p>
</li>
<li><p>Private company documents</p>
</li>
<li><p>Personal identification documents</p>
</li>
<li><p>Confidential school records</p>
</li>
</ul>
<p>Your application's privacy requirements depend on the type of data you're handling.</p>
<p>Don't treat an AI API as a place to casually upload every document on your computer.</p>
<p>Understand the provider's current data controls, retention behavior, and policies before deploying a file-processing application with sensitive information. OpenAI documents file retention and data controls in its platform documentation.</p>
<h2 id="heading-common-mistakes-that-developers-make">Common Mistakes that Developers Make</h2>
<h3 id="heading-common-mistake-1-putting-the-api-key-in-github">Common Mistake #1: Putting the API Key in GitHub</h3>
<p>Never do:</p>
<pre><code class="language-python">api_key = "your-secret-key"
</code></pre>
<p>and commit it.</p>
<p>Use environment variables instead.</p>
<h3 id="heading-common-mistake-2-assuming-the-ai-knows-everything-in-the-file">Common Mistake #2: Assuming the AI Knows Everything in the File</h3>
<p>Just because you upload a file doesn't mean your application can magically solve every possible question.</p>
<p>The model's ability to analyze a file depends on:</p>
<ul>
<li><p>File type</p>
</li>
<li><p>File size</p>
</li>
<li><p>File structure</p>
</li>
<li><p>Model capabilities</p>
</li>
<li><p>API limits</p>
</li>
<li><p>The quality of your instructions</p>
</li>
<li><p>The complexity of the question</p>
</li>
</ul>
<p>Design your application around those limitations.</p>
<h3 id="heading-common-mistake-3-telling-the-model-to-just-analyze-it">Common Mistake #3: Telling the Model to "Just Analyze It"</h3>
<p>This:</p>
<pre><code class="language-text">Analyze the file.
</code></pre>
<p>is extremely vague.</p>
<p>This is better:</p>
<pre><code class="language-text">Identify the main argument, summarize the evidence,
explain the methodology, and identify the limitations.
</code></pre>
<p>Clear instructions produce a clearer task.</p>
<h3 id="heading-common-mistake-4-ignoring-hallucinations">Common Mistake #4: Ignoring Hallucinations</h3>
<p>AI models can generate incorrect information.</p>
<p>That is why our instructions include:</p>
<pre><code class="language-text">Do not invent information.
</code></pre>
<p>and:</p>
<pre><code class="language-text">If the file does not contain enough information, say so.
</code></pre>
<p>You should still validate important information yourself.</p>
<p>For high-stakes applications, you need stronger evaluation and verification systems.</p>
<h3 id="heading-common-mistake-5-sending-huge-amounts-of-data-everywhere">Common Mistake #5: Sending Huge Amounts of Data Everywhere</h3>
<p>If you have thousands of documents, don't simply throw all of them into every request.</p>
<p>That is when retrieval systems become useful. Search first. Then give the model the most relevant information.</p>
<h3 id="heading-common-mistake-6-building-everything-at-once">Common Mistake #6: Building Everything at Once</h3>
<p>A common beginner mistake is starting with:</p>
<pre><code class="language-text">React
FastAPI
LangChain
PostgreSQL
Pinecone
Docker
Kubernetes
OpenAI
Authentication
RAG
Agents
</code></pre>
<p>all at the same time.</p>
<p>Please don't.</p>
<p>You will spend more time debugging infrastructure than learning AI.</p>
<p>Start with:</p>
<pre><code class="language-text">Python
+
OpenAI API
+
File
</code></pre>
<p>Get that working.</p>
<p>Then add features one at a time.</p>
<h2 id="heading-how-the-final-program-works">How the Final Program Works</h2>
<p>Let's summarize our program from beginning to end.</p>
<p>The user runs:</p>
<pre><code class="language-bash">python agent.py
</code></pre>
<p>The program asks:</p>
<pre><code class="language-text">Enter the path to your file:
</code></pre>
<p>The user enters:</p>
<pre><code class="language-text">research.pdf
</code></pre>
<p>Python checks whether the file exists.</p>
<p>Then the application uploads it:</p>
<pre><code class="language-python">client.files.create(...)
</code></pre>
<p>The API returns a file ID. The application stores that ID.</p>
<p>Then the user asks:</p>
<pre><code class="language-text">What is the main argument?
</code></pre>
<p>Our application sends:</p>
<pre><code class="language-text">Instructions
+
Question
+
File
</code></pre>
<p>to the model.</p>
<p>The model analyzes the information.</p>
<p>Then our program prints:</p>
<pre><code class="language-python">response.output_text
</code></pre>
<p>The user receives the answer.</p>
<p>And that's the core of a file-analysis AI agent.</p>
<h2 id="heading-the-most-important-code-to-remember">The Most Important Code to Remember</h2>
<p>If you forget everything else, remember this structure:</p>
<pre><code class="language-python">from openai import OpenAI
client = OpenAI()
with open("research.pdf", "rb") as file:
uploaded_file = client.files.create(
file=file,
purpose="user_data"
)
response = client.responses.create(
model="gpt-5",
instructions="Analyze the uploaded file carefully.",
input=[
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "What is the main argument?"
},
{
"type": "input_file",
"file_id": uploaded_file.id
}
]
}
]
)
print(response.output_text)
</code></pre>
<p>The important mental model is:</p>
<pre><code class="language-text">Open file
↓
Upload file
↓
Get file ID
↓
Send question + file ID
↓
Model analyzes file
↓
Print answer
</code></pre>
<p>Once you understand this flow, you can build much more complicated applications on top of it.</p>
<h2 id="heading-what-you-can-build-with-this">What You Can Build With This</h2>
<p>This simple project can become the foundation for many real applications.</p>
<h3 id="heading-ai-research-assistant">AI Research Assistant</h3>
<p>Upload academic papers and ask:</p>
<pre><code class="language-text">What is the research question?
</code></pre>
<pre><code class="language-text">What methodology was used?
</code></pre>
<pre><code class="language-text">What were the main findings?
</code></pre>
<h3 id="heading-resume-analyzer">Résumé Analyzer</h3>
<p>Upload a résumé and ask:</p>
<pre><code class="language-text">What skills are missing for this job?
</code></pre>
<h3 id="heading-study-assistant">Study Assistant</h3>
<p>Upload a textbook chapter and ask:</p>
<pre><code class="language-text">Explain this chapter in beginner-friendly language.
</code></pre>
<h3 id="heading-legal-document-assistant">Legal Document Assistant</h3>
<p>Upload a document and ask questions about its contents, while carefully considering privacy, accuracy, and appropriate legal safeguards.</p>
<h3 id="heading-business-report-analyzer">Business Report Analyzer</h3>
<p>Upload a report and ask:</p>
<pre><code class="language-text">What are the most important trends?
</code></pre>
<h3 id="heading-data-analysis-assistant">Data Analysis Assistant</h3>
<p>Upload a dataset and eventually give the agent access to Python-based analysis tools.</p>
<p>The possibilities are huge.</p>
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>Building an AI agent that can read files sounds complicated at first.</p>
<p>But when you break it down, the core idea is surprisingly simple.</p>
<ol>
<li><p>Your Python application does the setup.</p>
</li>
<li><p>The API provides access to the AI model.</p>
</li>
<li><p>The file provides the information.</p>
</li>
<li><p>The instructions define the agent's job.</p>
</li>
<li><p>The user provides the question.</p>
</li>
<li><p>The model analyzes the information and generates the response.</p>
</li>
</ol>
<p>The really interesting part is what happens next.</p>
<p>Once you understand how to give an AI model access to files, you can start adding retrieval, tools, databases, web search, memory, user interfaces, and multi-step workflows.</p>
<p>That's where simple AI scripts start turning into actual AI applications.</p>
<p>And the best part? You don't need to understand every piece of AI before you start building.</p>
<p>Start small and get one file working. Ask one question. Understand what every line of code does. Then add the next feature.</p>
<p>That's how you go from: "I want to build an AI agent" to "I actually built one".</p>
<p>Happy coding!</p>