Welcome to the final chapter of our tutorial series!
In the previous chapter, Payload Optimization, we learned how to shrink our data to make sure it fits into the AI's "context window." We made our system efficient.
Now, we must make our system resilient.
We are dealing with external AI services (APIs). Sometimes the internet is slow. Sometimes the AI service is down. Sometimes the data is weird. If our summary generator fails, what should happen to the rest of the application?
In this chapter, we will implement Non-Blocking Error Handling, ensuring our cosmetic features never crash the essential ones.
Imagine you are driving a car.
In our application:
If our summary generator crashes, we do not want the Agent to stop working. We simply want the summary to disappear silently.
Scenario: The user asks the Agent to "Create a database."
Desired Outcome:
null).To achieve this, we wrap our code in a Try-Catch block.
Think of it like a trapeze artist:
try: The artist attempts the flip (the code runs).catch: If they fall, the net catches them (the error logic runs).
If the try block succeeds, the catch block is skipped. If the try block explodes, the code instantly jumps to the catch block, preventing the explosion from affecting the rest of the program.
Let's look at how the data flows when things go wrong.
Let's look at toolUseSummaryGenerator.ts. We wrap almost the entire logic inside this safety structure.
This is where we attempt to do the work we defined in Chapters 2, 3, and 4.
// From file: toolUseSummaryGenerator.ts
export async function generateToolUseSummary(params): Promise<string | null> {
// ... check for empty tools ...
try {
// 1. Optimize data (Chapter 4)
// 2. Prepare System Prompt (Chapter 3)
// 3. Call AI API (Chapter 2)
const response = await queryHaiku({ /* ... */ })
// If successful, return the text
return summary || null
Explanation:
The try { ... } bracket opens a safe zone. Everything happening inside here is monitored. If queryHaiku fails because the internet is down, the code stops execution immediately and jumps to the catch block.
This block only runs if an error occurred above.
} catch (error) {
// Log but don't fail - summaries are non-critical
const err = toError(error)
// Tag the error so developers know where it came from
err.cause = { errorId: E_TOOL_USE_SUMMARY_GENERATION_FAILED }
// Write to the server logs (The "Black Box")
logError(err)
// Return null effectively says: "No summary available"
return null
}
}
Explanation:
catch (error): We capture the explosion.logError(err): We record the error in our system logs. This is like the car's dashboard light coming on. The car still drives, but the mechanic needs to know the radio broke.return null: This is the most important line. By returning null, we satisfy the function's contract without throwing an exception. The part of the app that called this function will just see null and know "Okay, I just won't show a label today."
You might remember in Payload Optimization that we also had a try-catch block inside truncateJson.
function truncateJson(value: unknown, maxLength: number): string {
try {
// Attempt to turn object to string
const str = jsonStringify(value)
// ...
} catch {
// If that fails, return a placeholder
return '[unable to serialize]'
}
}
Explanation: This is Granular Error Handling.
truncateJson fails, it returns a placeholder string. The summary generator continues.generateToolUseSummary returns null. The app continues.We have multiple layers of safety nets to ensure the user's experience is never interrupted by a cosmetic failure.
Congratulations! You have completed the Tool Use Summary tutorial series.
In this chapter, we learned:
try-catch blocks to prevent crashes.null effectively isolates failures so the main application keeps running smoothly.Let's review what you have built:
ToolInfo) to record robot actions.You now have a production-ready system that takes complex technical logs and converts them into beautiful, human-readable summaries without risking the stability of your application.
Happy Coding!
Generated by Code IQ