Skip to main content

Overview

SemanticTest supports three different input formats for passing data to blocks. This flexibility lets you write cleaner, more readable tests.

1. String Format (Simple)

Pass a single value from the DataBus:
{
  "block": "JsonParser",
  "input": "${response.body}"
}
What happens:
  • The value from response.body is wrapped in an object
  • Becomes: { body: "the actual value" }
  • The block receives it as inputs.body
When to use:
  • Single value input
  • Quick and simple syntax
  • Most common format

2. From/As Format (Mapping)

Map a DataBus slot to a specific parameter name:
{
  "block": "ValidateContent",
  "input": {
    "from": "parsed.message",
    "as": "text"
  }
}
What happens:
  • Value from parsed.message is mapped to parameter text
  • The block receives it as inputs.text
When to use:
  • Block expects a specific parameter name
  • You need to rename the data
  • More explicit about what data goes where
Example:
{
  "pipeline": [
    {
      "block": "HttpRequest",
      "input": { "url": "https://api.example.com/users" },
      "output": "response"
    },
    {
      "block": "JsonParser",
      "input": "${response.body}",
      "output": "parsed"
    },
    {
      "block": "ValidateContent",
      "input": {
        "from": "parsed.users[0].email",
        "as": "text"
      },
      "config": {
        "matches": ".*@.*\\.com"
      }
    }
  ]
}

3. Object Format (Full Control)

Pass multiple values with deep variable resolution:
{
  "block": "HttpRequest",
  "input": {
    "url": "${BASE_URL}/users",
    "method": "POST",
    "headers": {
      "Authorization": "Bearer ${token}",
      "Content-Type": "application/json"
    },
    "body": {
      "name": "John Doe",
      "email": "${userEmail}"
    },
    "timeout": 5000
  }
}
What happens:
  • All ${} variables are resolved from the DataBus
  • The entire object is passed to the block
  • Nested objects are fully resolved
When to use:
  • Multiple parameters needed
  • Complex nested data structures
  • Mix of static and dynamic values

Comparison

  • String Format
  • From/As Format
  • Object Format
// Simplest - single value
"input": "${response.body}"

// Block receives:
{
  body: "actual response body content"
}

Variable Resolution

All formats support ${} syntax for reading from the DataBus:
// Simple property access
"${response.status}"

// Nested properties
"${user.profile.email}"

// Array access
"${users[0].name}"

// From context
"${BASE_URL}"

// From environment
"${env.API_KEY}"

Best Practices

// Good - clear and simple
{
  "block": "JsonParser",
  "input": "${response.body}"
}

// Unnecessary complexity
{
  "block": "JsonParser",
  "input": {
    "from": "response.body",
    "as": "body"
  }
}
// ValidateContent expects 'text' parameter
{
  "block": "ValidateContent",
  "input": {
    "from": "response.message",
    "as": "text"
  }
}
// HttpRequest needs multiple parameters
{
  "block": "HttpRequest",
  "input": {
    "url": "${BASE_URL}/users",
    "method": "POST",
    "headers": {
      "Authorization": "Bearer ${token}"
    },
    "body": {
      "name": "${userName}",
      "email": "${userEmail}"
    }
  }
}
// Bad - confusing
{
  "input": {
    "from": "response.body",
    "as": "text",
    "url": "${API_URL}"  // ❌ Mixing from/as with object format
  }
}

// Good - use one format
{
  "input": {
    "text": "${response.body}",
    "url": "${API_URL}"
  }
}

Common Patterns

API Requests with Auth

{
  "block": "HttpRequest",
  "input": {
    "url": "${BASE_URL}/protected",
    "method": "GET",
    "headers": {
      "Authorization": "Bearer ${authToken}"
    }
  }
}

Validation with Specific Field

{
  "block": "ValidateContent",
  "input": {
    "from": "user.profile.bio",
    "as": "text"
  },
  "config": {
    "minLength": 10,
    "maxLength": 500
  }
}

Tool Validation

{
  "block": "ValidateTools",
  "input": {
    "from": "parsed.toolCalls",
    "as": "toolCalls"
  },
  "config": {
    "expected": ["search_database", "send_email"]
  }
}

Next Steps

I