Files and images
Your agent can read what the user attaches and hand files back, and send images to a vision model. Everything goes through the platform's intermediary with the turn's short-lived grant, the same one your connectors use: your agent never sees a storage key or a permanent link, and the grant expires with the turn.
Install version 0.4.0 or later: pip install "sofias-sdk-lite>=0.4.0".
What your agent receives
On every turn, the task message carries:
attachment_details: what the user attached (filename,content_type,byte_size,url), asAttachmentobjects. The previous turns' attachments are inmessages(the history), with the same kind of URL.files: aFileAccessto download those attachments and upload the files you return. It isNonewhen the platform sends no intermediary, for instance in a local run: check it before using it.
To receive attachments, enable "Can receive file attachments" in the portal.
Reading an attachment
def prepare_input(self, task, history, role):
texts = []
for attachment in task.attachment_details:
data = task.files.download(attachment) # bytes
if attachment.content_type == "text/csv":
texts.append(data.decode("utf-8"))
...
adownload is the async version. A refused download raises FileAccessError
with the HTTP status in status_code (for instance, 401 once the turn's grant
has expired).
Returning a file
Upload it with the turn's grant, then put its tag in your answer:
saved = task.files.upload("report.csv", csv_bytes, "text/csv")
answer = f"Here is the report.\n\n{saved.artifact()}"
The platform replaces the tag with the file, as a download in the user's chat. It only accepts files uploaded (or attached) in a turn of the same conversation and by the same agent. Limits: 25 MB per file and 10 returned files per turn.
Images for a vision model
image_part downloads an image attachment and builds an OpenAI-compatible
content part:
part = task.files.image_part(attachment)
messages = [{"role": "user", "content": [{"type": "text", "text": "What is in this picture?"}, part]}]
Select a vision model for your agent in the portal. It reaches the container in
SOFIAS_VISION_MODEL, with its gateway in SOFIAS_VISION_BASE_URL and
SOFIAS_VISION_API_KEY:
import os
from sofias_sdk_lite.llm.gateway import GatewayLLM
vision = GatewayLLM(
base_url=os.environ["SOFIAS_VISION_BASE_URL"],
api_key=os.environ["SOFIAS_VISION_API_KEY"],
model=os.environ["SOFIAS_VISION_MODEL"],
)
Tool calls in the sandbox logs
Every tool the model calls, yours or a connector's, leaves one line on standard output:
SOFIAS_EVENT {"type":"tool_call","tool":"search","server":"notion","ok":true,"duration_ms":412,...}
The portal's sandbox shows them as a timeline of the tools your agent called.
They carry names, timings and outcome only, never arguments or results. Set
SOFIAS_EVENTS=off to silence them.