Attachments¶
The AttachmentLoader (and its async sibling
AsyncAttachmentLoader) pulls records from the ServiceNow
sys_attachment table. Each attachment row carries metadata about a
file: its name, content type, size, and the parent record it belongs to
(via table_name + table_sys_id).
Two access modes¶
The loader supports two ways of working with files:
Metadata only (default). Each
SnowDocumentdescribes one attachment without fetching its bytes. Pull binary content explicitly for the attachments you actually need viadownload()ordownload_to().Eager download. Pass
download=Trueand the loader fetches every file’s bytes during iteration, storing them undermetadata["content_bytes"]. Usemax_size_bytesto skip files above a given threshold.
Quick start¶
from snowloader import SnowConnection, AttachmentLoader
conn = SnowConnection(
instance_url="https://mycompany.service-now.com",
username="admin",
password="password",
)
# Pull metadata for every KB attachment
loader = AttachmentLoader(
connection=conn,
query="table_name=kb_knowledge",
)
for doc in loader.lazy_load():
print(doc.metadata["file_name"], doc.metadata["size_bytes"])
Download a specific file¶
from pathlib import Path
loader = AttachmentLoader(connection=conn, query="table_name=kb_knowledge")
first = next(iter(loader.lazy_load()))
loader.download_to(first.metadata["sys_id"], Path("./out") / first.metadata["file_name"])
Eager download with size cap¶
loader = AttachmentLoader(
connection=conn,
query="table_name=incident",
download=True,
max_size_bytes=10 * 1024 * 1024, # skip files over 10 MB
)
for doc in loader.lazy_load():
blob = doc.metadata.get("content_bytes")
if blob is not None:
process(doc.metadata["file_name"], blob)
Async usage¶
import asyncio
from snowloader import AsyncSnowConnection, AsyncAttachmentLoader
async def main() -> None:
async with AsyncSnowConnection(
instance_url="https://mycompany.service-now.com",
username="admin",
password="password",
) as conn:
loader = AsyncAttachmentLoader(
connection=conn,
query="table_name=kb_knowledge",
download=True,
)
docs = await loader.aload()
asyncio.run(main())
Document layout¶
Each SnowDocument produced by the attachment loader has:
page_content: a short summary line including the file name, content type, size, and parent recordmetadatakeys:sys_id: the attachment’s own sys_idfile_name,content_type,size_bytestable_name,table_sys_id: pointer to the parent recorddownload_url: full URL to the binary endpointcontent_bytes: present only whendownload=Trueand the file was withinmax_size_bytes
LangChain and LlamaIndex adapters¶
Both framework adapters include attachment variants:
from snowloader.adapters.langchain import ServiceNowAttachmentLoader
from snowloader.adapters.llamaindex import ServiceNowAttachmentReader
The async forms are AsyncServiceNowAttachmentLoader and
AsyncServiceNowAttachmentReader.