# Workflow References

References let action configs consume workflow inputs and previous step outputs.

## Syntax

```text
{{input://input-id}}
{{step://step-id}}
{{step://step-id?path=data[items]}}
{{step://step-id?format=json}}
{{step://step-id?path=file&format[file]=raw}}
{{variableName}}
```

Prefer helper functions:

```typescript
const topic = tela.createWorkflowInput({ id: 'input-topic', name: 'topic', type: 'text' })
const first = tela.llmNode({ name: 'Draft', prompt: `Write about ${tela.inputRef(topic)}` })
const second = tela.llmNode({ name: 'Summary', prompt: `Summarize ${tela.stepRef(first)}` })
```

## URI Parts

| Part | Meaning |
|---|---|
| `input://id` | Workflow input. Use stable input IDs when possible. |
| `step://id` | Step output by node ID. |
| `path` | Nested extraction. Repeat for multi-path zipping. |
| `format` | Global output format override. |
| `format[path]` | Per-path format override. |

## Paths

Path syntax uses bracket notation:

| Path | Result |
|---|---|
| `data` | `value.data` |
| `data[items]` | `value.data.items` |
| `data[items][0]` | First item |
| `data[items][name]` | Auto-map names from every item |

When multiple `path` params are provided, values are zipped:

```text
{{step://fetch?path=users[name]&path=users[email]}}
```

## Formats

Available formats:

| Format | Behavior |
|---|---|
| `raw` | Preserve original type. Always available. |
| `string` | String representation. |
| `json` | JSON string. |
| `ai-xml` | AI-friendly XML. |

Each action field declares accepted reference types and formats. If a workflow is already saved, call:

```typescript
await tela.getStepDependencies(promptId, versionId, stepId)
```

Use returned `compatibility` data instead of guessing.

## Exact vs Embedded References

If the whole field is a reference, resolved type is preserved:

```typescript
file: `{{step://${split.id}?path=file}}` // file object/array stays structured
```

If embedded in text, value is stringified/formatted:

```typescript
prompt: `Summarize this: {{step://${split.id}?path=file&format=ai-xml}}`
```

## Common Patterns

### Workflow input

```typescript
const invoice = tela.createWorkflowInput({ id: 'input-invoice', name: 'invoice', type: 'file' })
const split = tela.documentSplitterNode({
  name: 'Split invoice',
  file: tela.inputRef(invoice, { format: 'raw' }),
})
```

### Step output path

```typescript
const total = tela.stepRef(extract, { path: 'total' })
```

### File into LLM as raw/multimodal

```typescript
const readPage = tela.llmNode({
  name: 'Read Page',
  prompt: `Read this page: ${tela.stepRef(split, { format: 'raw' })}`,
})
```

### Map variable

Inside a map subgraph, use the `mapVariable` directly:

```typescript
const mapPages = tela.mapNode({ name: 'Pages', over: tela.stepRef(split), mapVariable: 'page' })
const extract = tela.llmNode({ name: 'Extract Page', prompt: 'Extract data from {{page}}' })
```

### Condition selector

Use canonical refs in selector conditions:

```typescript
const route = tela.conditionNode({
  name: 'Route',
  cases: [{ name: 'Large', condition: `${tela.stepRef(extract, { path: 'amount' })}|greater_than|1000` }],
})
```

### Code node

References are not resolved inside code strings. Use computed input by step name:

```typescript
const aggregate = tela.codeExecutionNode({
  name: 'Aggregate',
  code: `function execute(input) { return { total: input["Extract Page"].amount } }`,
})
```
