> ## Documentation Index
> Fetch the complete documentation index at: https://developer.opus.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Opus Code

> Write custom Python code when you need logic that other tasks can't handle.

Opus Code lets you write Python code directly in your workflow. Use it when you need custom logic or data transformations that other tasks can't handle. Your code runs in a secure environment with access to data from earlier steps in your workflow.

## Key Capabilities

<CardGroup cols={2}>
  <Card title="Python 3.13" icon="python">
    Write and run Python code in a secure environment.
  </Card>

  <Card title="Use Workflow Data" icon="brackets-curly">
    Read data from earlier steps and pass results to later steps.
  </Card>

  <Card title="Custom Logic" icon="gear">
    Do calculations, transformations, validations—anything you can code.
  </Card>

  <Card title="Call APIs" icon="plug">
    Connect to services not supported by integrations or External Service.
  </Card>
</CardGroup>

## When to Use It

Use Opus Code when you need to do something that other tasks can't handle. Common examples:

* Transform data into a different format
* Calculate values or run business logic
* Clean up messy data before using it
* Call an API that isn't supported by the Integration Marketplace or [External Service](/tasks/data/external-service) task
* Validate that data matches what you expect

<Note>
  Keep your code simple and focused. If you need to do multiple things, use multiple Opus Code tasks instead of a big one—it's easier to debug.
</Note>

## Reading and Writing Data

Your code can read data from earlier steps and pass results to later steps using a special syntax:

```python theme={null}
# Read an input variable
my_value = {{ input_variable_name }}

# Write to an output variable
{{ output_variable_name }} = my_value
```

**Input variables** are read-only—you can read them but not change them.

**Output variables** send data out from your code to later steps.

## Working with Files

Inside an Opus Code task, an `Opus` object is pre-defined and ready to use—no import needed. Use it to work with files in Opus storage: download an existing file, create a new one, and upload results back to storage so later steps can use them.

All file operations live under `Opus.file`:

* `Opus.file.download(url)` — fetch a file from Opus storage by URL, returning an `OpusFile` you can read and modify locally.
* `Opus.file.create(name, type)` — create a new empty `OpusFile` of a given type (for example `"CSV"` or `"PDF"`).
* `Opus.file.upload(file)` — upload an `OpusFile` back to storage and get a new file URL.

`Opus.file.presigned_download(url)` (for a temporary download link) and the read/write methods on the returned `OpusFile` (such as `read_text`, `write_text`, `read_bytes`, `write_bytes`, and `open`) round out the API.

```python theme={null}
# Download a CSV, modify it, and upload the result
file = Opus.file.download("https://files.opus.com/reports/data.csv")
original = file.read_text()
modified = original.replace("old_value", "new_value")
file.write_text(modified)

new_url = Opus.file.upload(file)
```

<Note>
  Downloaded files are modified locally only. Changes aren't saved back to Opus storage until you call `Opus.file.upload`, which creates a new file and returns a new URL—the original remote file is never modified.
</Note>

See the [Opus SDK](/opus-sdk/overview) for the full file API (including the `OpusFile` interface and error handling), and [Working with File Formats](/opus-sdk/file-formats) for per-format recipes covering CSV, XLSX, PDF, DOCX, and more.

## Supported Packages

Opus Code comes with these Python packages pre-installed. See [Available Packages](/opus-sdk/available-packages) for the complete, up-to-date list.

| Category              | Packages                                                           |
| --------------------- | ------------------------------------------------------------------ |
| **Data**              | json, csv, collections, dataclasses, enum, copy                    |
| **Text**              | re, string, html                                                   |
| **Math**              | math, statistics, random, decimal, fractions                       |
| **Time**              | datetime, time, python-dateutil                                    |
| **Utilities**         | itertools, functools, typing, uuid                                 |
| **Encoding**          | hashlib, base64                                                    |
| **Markup & Archives** | xml, zipfile                                                       |
| **Advanced**          | abc, warnings, contextlib, concurrent, concurrent.futures          |
| **HTTP**              | requests                                                           |
| **Office Documents**  | openpyxl, python-docx, python-pptx                                 |
| **PDF**               | PyPDF2, pdfplumber, pymupdf, reportlab, fpdf2, pdf2docx, pdf2image |
| **Images**            | pillow, opencv-python-headless                                     |
| **Other**             | python-magic, toon-format                                          |

## How to Add Opus Code

<Steps>
  <Step title="Drop it into your workflow">
    Drag an Opus Code task into your workflow.
  </Step>

  <Step title="Set up your inputs">
    Add input variables and connect them to data from earlier steps.
  </Step>

  <Step title="Write your code">
    Write your Python code in the editor. Read inputs and assign values to outputs.
  </Step>

  <Step title="Set up your outputs">
    Add output variables that later steps can use.
  </Step>

  <Step title="Test it">
    Run a preview to make sure your code works with real data.
  </Step>
</Steps>

## Tips for Better Results

<AccordionGroup>
  <Accordion title="Keep it simple">
    One task, one job:

    * Do one focused thing per Opus Code task
    * Use multiple small tasks instead of one big one
    * Easier to debug when something goes wrong
  </Accordion>

  <Accordion title="Check your inputs first">
    Validate data at the start of your code:

    * Make sure required fields exist
    * Check that data is the type you expect
    * Handle empty or missing data gracefully
  </Accordion>

  <Accordion title="Handle errors">
    Plan for things going wrong:

    * Use try/except to catch errors
    * Set an error output so later steps know something failed
    * Write clear error messages
  </Accordion>

  <Accordion title="Test with preview">
    Before activating your workflow:

    * Run preview with realistic test data
    * Check that outputs look correct
    * Try edge cases to make sure your code handles them
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="Opus SDK" icon="cube" href="/opus-sdk/overview">
    Work with files in Opus storage using the pre-defined `Opus` object.
  </Card>

  <Card title="Working with File Formats" icon="file-lines" href="/opus-sdk/file-formats">
    Per-format recipes for CSV, XLSX, PDF, DOCX, and more.
  </Card>

  <Card title="Available Packages" icon="box-open" href="/opus-sdk/available-packages">
    Browse the full list of Python packages you can import.
  </Card>

  <Card title="External Service" icon="plug" href="/tasks/data/external-service">
    Call external APIs without writing code.
  </Card>

  <Card title="Opus Agent" icon="robot" href="/tasks/agent/opus-agent">
    Use AI to handle tasks instead of writing code.
  </Card>

  <Card title="Custom Agent" icon="sliders" href="/tasks/agent/custom-agent">
    Get structured outputs from an LLM.
  </Card>

  <Card title="Workflows" icon="diagram-project" href="/guides/workflows">
    Learn how all the pieces fit together.
  </Card>

  <Card title="Builder" icon="hammer" href="/guides/builder">
    Design, configure, and test your workflow in the visual editor.
  </Card>
</CardGroup>
