context.work_dir
A per-run scratch directory you can write to.
context.work_dir # → str, absolute path
import os
path = os.path.join(context.work_dir, 'export.csv')
with open(path, 'w', encoding='utf-8') as f:
f.write('header1,header2\n')
f.write('value1,value2\n')
context.logger.info(f"Wrote export to {path}")
Created lazily on first access — if you never touch context.work_dir,
no directory is created.
What it's actually pointing at
| Environment | Path | Lifecycle |
|---|---|---|
| Production | /tmp/connector_run/<entrypoint_key>_<YYYYMMDD-HHMMSS-fff>/ inside the Docker container | Wiped when the container exits at end of job |
| Toolkit | <repo>/temp_work/<entrypoint_key>_<YYYYMMDD-HHMMSS-fff>/ | Persists between runs so you can inspect what your entrypoint produced — each run gets its own timestamped subdirectory |
In both environments the path is isolated per entrypoint — two entrypoints running side-by-side don't see each other's files.
What to use it for
| Good fit | Why |
|---|---|
Attachment downloads — att.save(name) writes here by default | Lives only as long as the run needs it |
| CSV / Excel exports you're about to SFTP push | Build → push → forget |
| Intermediate files during parsing — split a multi-invoice PDF | Cleaned up automatically |
| Debug dumps — write the raw external payload before you transform it | Toolkit keeps it; production discards it |
What NOT to use it for
Don't treat it as durable storage
It's gone the moment the container exits. If you need anything to survive across runs, write it to:
- Nuntiq (via
context.api— entity Loads, custom data tables, lifecycle messages). - An external system (SFTP push, S3 put, ERP API).
- The structured log (small observability metadata only).
Don't escape the directory
work_dir is a single absolute path. Don't construct paths with ../ or
absolute paths that point outside it. The framework rejects escapes by
asserting paths stay inside work_dir, but the cleanest pattern is to always
use os.path.join(context.work_dir, name).
# ❌
path = '/tmp/something.csv' # outside work_dir
path = os.path.join(context.work_dir, '../foo') # escapes
# ✅
path = os.path.join(context.work_dir, 'something.csv')
Don't shell-out and cd somewhere else
Subprocess calls inherit the container's working directory, which is
/tmp/job/ — not context.work_dir. If you shell out (e.g. to gpg or
ffmpeg), pass absolute paths.
Attachments — the common case
Every attachment you pull off an invoice already knows about context, so
calling att.save(filename) writes into context.work_dir without extra
plumbing:
for att in invoice.attachments:
local_path = att.save(att.file_name) # writes to context.work_dir
context.logger.info(f"Saved {att.file_name} to {local_path}")
# Or just read into memory:
data = att.read_bytes()
text = att.read_base64()
See Invoice claim flow for the full pattern, and
SFTP push for a real example that builds files in
work_dir, uploads them, and lets the cleanup happen on container exit.