Skip to main content

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

EnvironmentPathLifecycle
Production/tmp/connector_run/<entrypoint_key>_<YYYYMMDD-HHMMSS-fff>/ inside the Docker containerWiped 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 fitWhy
Attachment downloadsatt.save(name) writes here by defaultLives only as long as the run needs it
CSV / Excel exports you're about to SFTP pushBuild → push → forget
Intermediate files during parsing — split a multi-invoice PDFCleaned up automatically
Debug dumps — write the raw external payload before you transform itToolkit 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.