Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions examples/agent_with_file_upload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# To run the example:
# poetry install
# poetry run python examples/agent_with_file_upload.py

from glean.api_client import Glean, models
import os


def main():
with Glean(
api_token=os.getenv("GLEAN_API_TOKEN", ""),
domain=os.getenv("GLEAN_DOMAIN", "customerName"),
) as glean:

# 1. Upload the file first
file_content = b"name,role\nAlice,Engineer\nBob,Manager"

upload_result = glean.client.chat.upload_files(
files=[
models.File(
file_name="employees.csv",
content=file_content
)
]
)

# 2. Get the ID (string) from the response
file_id = upload_result.files[0].id

# 3. Run the agent passing the file ID (NOT the file object)
res = glean.client.agents.run(
agent_id=os.getenv("GLEAN_AGENT_ID", "<agent-id>"),
input={
# Pass the file ID string to the input parameter
"file": file_id,
"query": "Who is the manager?"
}
)

print(res)

if __name__ == "__main__":
main()
81 changes: 81 additions & 0 deletions src/glean/api_client/_hooks/agent_file_upload_error_hook.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"""Custom hook to provide helpful error messages for agent file upload issues."""

from typing import Optional, Tuple, Union
import httpx
from glean.api_client._hooks.types import AfterErrorContext, AfterErrorHook


class AgentFileUploadErrorHook(AfterErrorHook):
"""
Hook that detects when users incorrectly pass file objects to agents.run()
and provides clear guidance on the correct two-step upload workflow.

This hook intercepts 400 errors from agent run operations that contain
"permission" in the error message, which typically indicates a file was
passed incorrectly instead of a file ID.
"""

def after_error(
self,
hook_ctx: AfterErrorContext,
response: Optional[httpx.Response],
error: Optional[Exception],
) -> Union[Tuple[Optional[httpx.Response], Optional[Exception]], Exception]:
"""
Intercept agent run errors and enhance them with helpful file upload guidance.

Args:
hook_ctx: Context about the operation being performed
response: The HTTP response (if available)
error: The exception that was raised

Returns:
Either a tuple of (response, error) to continue normal error handling,
or a new Exception to replace the original error.
"""
# Only intercept 400 errors from agent run operations
if (
response is not None
and response.status_code == 400
and hook_ctx.operation_id in ["createAndWaitRun", "createAndStreamRun"]
):
error_message = str(error) if error else ""

# Check if this looks like a file upload error
# (API returns "permission" error when file objects are passed incorrectly)
if "permission" in error_message.lower():
# Create enhanced error message with clear instructions
enhanced_message = (
"Agent file upload error: When using agents with file inputs, "
"you must follow a two-step process:\n"
"\n"
"1. First, upload files using client.chat.upload_files():\n"
" from glean.api_client import models\n"
" \n"
" # Upload the file\n"
" upload_result = client.chat.upload_files(\n"
" files=[\n"
" models.File(\n"
" file_name='data.csv',\n"
" content=file_content # bytes or file-like object\n"
" )\n"
" ]\n"
" )\n"
"\n"
"2. Then, pass the returned file IDs (not file objects) in the input field:\n"
" result = client.agents.run(\n"
" agent_id='<agent-id>',\n"
" input={\n"
" 'my_file': upload_result.files[0].id # Use the file ID string\n"
" }\n"
" )\n"
"\n"
"For a complete example, see: examples/agent_with_file_upload.py\n"
f"\nOriginal error: {error_message}"
)

# Return new exception with enhanced message
return Exception(enhanced_message)

# Pass through all other errors unchanged
return response, error
4 changes: 4 additions & 0 deletions src/glean/api_client/_hooks/registration.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .types import Hooks
from .multipart_fix_hook import MultipartFileFieldFixHook
from .agent_file_upload_error_hook import AgentFileUploadErrorHook


# This file is only ever generated once on the first generation and then is free to be modified.
Expand All @@ -15,3 +16,6 @@ def init_hooks(hooks: Hooks):

# Register hook to fix multipart file field names that incorrectly have '[]' suffix
hooks.register_sdk_init_hook(MultipartFileFieldFixHook())

# Register hook to provide helpful error messages for agent file upload issues
hooks.register_after_error_hook(AgentFileUploadErrorHook())