Files

Agents generate files during runs (CSV, JSON, Markdown, HTML, code, plain text). Instruct the agent to write them, then download through the API.

Generate files

Tell the agent what to produce in the task instructions, then poll for completion:

Python
from m8tes import M8tes

client = M8tes()

run = client.runs.create(
    agent_id=1,
    message="Analyze our open support tickets and write a CSV summary to tickets_report.csv",
    stream=False,
)
run = client.runs.poll(run.id)

Upload files to a run

Attach files for the agent to work on: a CSV to analyze, a PDF to summarize. Pass files= to runs.create (a path, a (filename, bytes) tuple, or an open binary file); every other argument works the same:

run = client.runs.create(
    agent_id=1,
    message="Summarize the Q3 numbers in this spreadsheet",
    files=["q3-report.csv"],
    stream=False,
)

The payload form field carries the same JSON as POST /runs (teammate_id is the wire name for the agent id; the SDK accepts agent_id alike). Uploaded files land in the run's working directory and their names are appended to the prompt, so the agent finds them without extra instructions. Limits: 20 files, 100MB per file, 500MB per request.

The Platform picker uses the same size limits and supported formats as the API: images (JPEG, PNG, GIF, WebP), PDF, text and code, CSV, XML/YAML, ZIP/GZIP/TAR, and Office documents (DOCX, XLS/XLSX, PPT/PPTX). Missing or generic binary MIME types are inferred from supported filename extensions; explicit unsupported MIME types are rejected. The browser MIME alias video/mp2t is treated as TypeScript only for .ts files. JavaScript accepts both application/javascript and text/javascript.

Attachments are also recorded on each user message: client.runs.messages(run.id) returns event_metadata["attachments"], a list of { "name": "q3-report.csv", "size": 1234 } entries. Names are the sanitized filenames in the sandbox; sizes are bytes. Follow-ups record only their new attachments. Join-stream user_message events carry the same list as attachments. Older messages may not have this metadata.

Keep and share an output

Run files live in the run's sandbox and latest-report is rewritten on the next run. Promote the ones worth keeping into an artifact: a durable copy linked to the run, task, and agent, versioned per agent + name (so a weekly report is v1, v2, v3…), and shareable with a public link — the same model as sharing a run.

Python
artifact = client.artifacts.create(run_id=run.id, filename="latest-report.md")
print(artifact.version, artifact.size_bytes)

share = client.artifacts.share(artifact.id)
print(share.share_url)  # anyone with the link can open it — revoke with client.artifacts.unshare(artifact.id)

report = client.artifacts.download(artifact.id)  # raw bytes, authenticated

A run's latest-report.md is promoted automatically when the run finishes (and again on each follow-up turn, keeping the same artifact current), so client.artifacts.list(agent_id=1) is the report history for that agent. Artifacts are capped at 10 MB (a larger file is refused with a validation_error); uploaded input files are never promotable; promotion is idempotent per run + filename.

List and download files

Python
files = client.runs.list_files(run.id)
for f in files:
    print(f.name, f.size)

content = client.runs.download_file(run.id, filename="tickets_report.csv")
with open("tickets_report.csv", "wb") as fh:
    fh.write(content)

Need live progress while files are written? See the streaming tracker below; otherwise just call list_files after the run completes.

Advanced: track file writes via streaming

Tool arguments stream as JSON fragments on tool-call-delta events; tool-call-start carries only tool_name and tool_call_id. To see filenames in real time, accumulate the deltas for each Write call and parse them on tool-call-end:

Python
import json

write_args = {}  # tool_call_id -> accumulated JSON arguments

with client.runs.create(
    agent_id=1,
    message="""Generate a weekly performance report:
1. Write an executive summary to weekly_summary.md
2. Export raw metrics to metrics.csv
3. Save top performers to top_10.json""",
) as stream:
    for event in stream:
        if event.type == "text-delta":
            print(event.delta, end="", flush=True)
        elif event.type == "tool-call-start" and event.tool_name == "Write":
            write_args[event.tool_call_id] = ""
        elif event.type == "tool-call-delta" and event.tool_call_id in write_args:
            write_args[event.tool_call_id] += event.delta
        elif event.type == "tool-call-end" and event.tool_call_id in write_args:
            path = json.loads(write_args.pop(event.tool_call_id)).get("file_path", "")
            print(f"\n  writing {path.split('/')[-1]}...")
    run_id = stream.run_id

# Download everything the run wrote
for f in client.runs.list_files(run_id):
    with open(f.name, "wb") as fh:
        fh.write(client.runs.download_file(run_id, f.name))
Example: weekly report pipeline

Combine file generation with scheduling for recurring reports:

Python
reporter = client.agents.create(
    name="weekly reporter",
    tools=["stripe", "googlesheets", "gmail"],
    instructions=(
        "Generate weekly reports. Write a markdown summary to weekly_report.md "
        "and a CSV of raw data to weekly_data.csv. Email the summary to the team."
    ),
)

task = client.tasks.create(
    agent_id=reporter.id,
    instructions=(
        "Pull last week's key metrics from Stripe and Google Sheets. "
        "Write weekly_report.md and weekly_data.csv. "
        "Email weekly_report.md to team@acme.com."
    ),
    schedule="0 9 * * 1",
    schedule_timezone="America/New_York",
)

run = client.tasks.run_and_wait(task.id)

for f in client.runs.list_files(run.id):
    print(f.name, f.size)

See examples/file-report.py for the full pipeline: streaming progress, scheduled generation, and download.

Tips: reliable file output

Be specific in your task instructions. Name the file, the format, and the columns:

Python
run = client.runs.create(
    agent_id=1,
    message="Query open tickets, then write a CSV with columns: id, subject, priority. Save as tickets.csv",
    stream=False,
)

For multiple files, number them in one message ("1. Write a summary to report.md, 2. Export metrics.csv, ...") as in the streaming example above.

Next: Runs · Streaming & Events · Scheduling

Was this page helpful?