> For the complete documentation index, see [llms.txt](https://whitepaper.aitech.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://whitepaper.aitech.io/agentforge/connections/accessing-data.md).

# accessing data

Once blocks are connected, you can access data from source blocks in destination blocks using connection tags and various data access techniques.

### Basic Data Access

The simplest way to access data is through direct references using connection tags:

| Example         | Annotation                            |
| --------------- | ------------------------------------- |
| Simple Property | `<block.content>`                     |
| Nested Property | `<block.tokens.total>`                |
| Array Element   | `<block.items[0].name>`               |
| Complex Path    | `<block.data.users[2].profile.email>` |

### Advanced Data Access Techniques

#### Array Access

You can access array elements using square bracket notation:

```javascript
// Access the first item in an array
<block.items[0]>

// Access a specific property of an array item
<block.items[2].name>

// Access the last item in an array (in Function blocks)
const items = input.block.items;
const lastItem = items[items.length - 1];
```

#### Object Property Access

Access object properties using dot notation:

```javascript
// Access a simple property
<block.content>

// Access a nested property
<block.data.user.profile.name>

// Access a property with special characters (in Function blocks)
const data = input.block.data;
const specialProp = data['property-with-dashes'];
```

#### Dynamic References

Connection references are evaluated at runtime, allowing for dynamic data flow through your workflow:

```javascript
// In a Function block, you can access connected data
const userName = input.userBlock.name;
const orderTotal = input.apiBlock.body.order.total;

// Process the data
const discount = orderTotal > 100 ? 0.1 : 0;
const finalPrice = orderTotal * (1 - discount);

// Return the result
return {
  userName,
  originalTotal: orderTotal,
  discount: discount * 100 + '%',
  finalPrice
};
```

### Data Transformation

#### Using Function Blocks

Function blocks are the most powerful way to transform data between connections:

```javascript
// Example: Transform API response data
const apiResponse = input.apiBlock.data;
const transformedData = {
  users: apiResponse.results.map(user => ({
    id: user.id,
    fullName: `${user.firstName} ${user.lastName}`,
    email: user.email.toLowerCase(),
    isActive: user.status === 'active'
  })),
  totalCount: apiResponse.count,
  timestamp: new Date().toISOString()
};

return transformedData;
```

#### String Interpolation

You can combine connection tags with static text:

```
Hello, <userBlock.name>! Your order #<orderBlock.id> has been processed.
```

#### Conditional Content

In Function blocks, you can create conditional content based on connected data:

```javascript
const user = input.userBlock;
const orderTotal = input.orderBlock.total;

let message = `Thank you for your order, ${user.name}!`;

if (orderTotal > 100) {
  message += " You've qualified for free shipping!";
} else {
  message += ` Add $${(100 - orderTotal).toFixed(2)} more to qualify for free shipping.`;
}

return { message };
```

### Handling Missing Data

It's important to handle cases where connected data might be missing or null:

{% hint style="warning" %}
Always validate connected data before using it, especially when accessing nested properties or array elements.
{% endhint %}

#### Default Values

In Function blocks, you can provide default values for missing data:

```javascript
const userName = input.userBlock?.name || 'Guest'
const items = input.orderBlock?.items || []
const total = input.orderBlock?.total ?? 0
```

#### Conditional Checks

Check if data exists before accessing nested properties:

```javascript
let userEmail = 'No email provided'
if (input.userBlock && input.userBlock.contact && input.userBlock.contact.email) {
  userEmail = input.userBlock.contact.email
}
```

#### Optional Chaining

In Function blocks, use optional chaining to safely access nested properties:

```javascript
const userCity = input.userBlock?.address?.city
const firstItemName = input.orderBlock?.items?.[0]?.name
```

### Debugging Connection Data

When troubleshooting connection issues, these techniques can help:

1. **Log Data**: In Function blocks, use `console.log()` to inspect connected data
2. **Return Full Objects**: Return the full input object to see all available data
3. **Check Types**: Verify the data types of connected values
4. **Validate Paths**: Ensure you're using the correct path to access nested data

```javascript
// Example debugging function
function debugConnections() {
  console.log('All inputs:', input)
  console.log('User data type:', typeof input.userBlock)
  console.log('Order items:', input.orderBlock?.items)

  return {
    debug: true,
    allInputs: input,
    userExists: !!input.userBlock,
    orderItemCount: input.orderBlock?.items?.length || 0,
  }
}
```
