HTTP Transitions

HTTP Transitions – The Complete Guide to External API Integration in Agentic Nets

The HTTP transition is the integration powerhouse in Agentic Nets. While Pass and Map transitions handle internal token routing and transformation, HTTP transitions enable your agentic processes to communicate with the outside world – calling REST APIs, webhooks, microservices, and any HTTP endpoint.

In this comprehensive guide, we’ll explore every capability of HTTP transitions:

  • HTTP methods – GET, POST, PUT, DELETE, PATCH
  • Template interpolation – dynamic URLs, headers, and request bodies
  • Authentication – Basic, Bearer, API Key
  • Retry logic – configurable retries with exponential backoff
  • Timeout handling – per-request timeout configuration
  • Response routing – success/error paths with conditional emit
  • Multi-emit patterns – routing responses to multiple destinations
  • Token metadata – including source token info in requests

Anatomy of an HTTP Transition Inscription

Every HTTP transition inscription follows this structure:

{
  "id": "t-my-api-call",
  "kind": "task",
  "mode": "SINGLE",

  "presets": {
    "input": {
      "placeId": "requests-queue",
      "host": "myModel@localhost:8080",
      "arcql": "FROM $ LIMIT 1",
      "take": "FIRST",
      "consume": true
    }
  },

  "postsets": {
    "success": { "placeId": "success-queue", "host": "myModel@localhost:8080" },
    "error": { "placeId": "error-queue", "host": "myModel@localhost:8080" }
  },

  "action": {
    "type": "http",
    "method": "POST",
    "url": "https://api.example.com/orders/${input.data.orderId}",
    "headers": {
      "Content-Type": "application/json",
      "X-Request-Id": "${requestId}"
    },
    "body": {
      "orderId": "${input.data.orderId}",
      "amount": "${input.data.amount}"
    },
    "timeoutMs": 30000
  },

  "emit": [
    { "to": "success", "from": "@response.json", "when": "success" },
    { "to": "error", "from": "@input.data", "when": "error" }
  ]
}

Key elements:

  • kind: "task" – identifies this as an HTTP action transition
  • action.type: "http" – specifies the HTTP action handler
  • action.method – HTTP method (GET, POST, PUT, DELETE, PATCH)
  • action.url – target URL with template interpolation
  • emit.from – what to emit: @response.json, @response.meta, or @input.data

HTTP Methods

HTTP transitions support all standard HTTP methods:

GET – Retrieve Data

{
  "action": {
    "type": "http",
    "method": "GET",
    "url": "https://api.example.com/orders/${input.data.orderId}"
  }
}

POST – Create Resources

{
  "action": {
    "type": "http",
    "method": "POST",
    "url": "https://api.example.com/orders",
    "headers": { "Content-Type": "application/json" },
    "body": {
      "customerId": "${input.data.customerId}",
      "items": "${input.data.items}",
      "total": "${input.data.total}"
    }
  }
}

PUT – Update Resources

{
  "action": {
    "type": "http",
    "method": "PUT",
    "url": "https://api.example.com/orders/${input.data.orderId}",
    "headers": { "Content-Type": "application/json" },
    "body": {
      "status": "shipped",
      "trackingNumber": "${input.data.trackingNumber}"
    }
  }
}

DELETE – Remove Resources

{
  "action": {
    "type": "http",
    "method": "DELETE",
    "url": "https://api.example.com/orders/${input.data.orderId}"
  }
}

Template Interpolation

HTTP transitions use the same ${...} template syntax as Map transitions, enabling dynamic request construction from token data.

URL Path Interpolation

Embed token data directly in URL paths:

// Input token
{ "resourceId": "resource-xyz", "action": "status" }

// URL template
"url": "https://api.example.com/resources/${input.data.resourceId}/${input.data.action}"

// Result
"https://api.example.com/resources/resource-xyz/status"

Query Parameter Interpolation

Build dynamic query strings:

// Input token
{ "orderId": "ORD-12345", "customerId": "CUST-999" }

// URL template with query params
"url": "https://api.example.com/search?orderId=${input.data.orderId}&customerId=${input.data.customerId}"

// Result
"https://api.example.com/search?orderId=ORD-12345&customerId=CUST-999"

Header Interpolation

Include token data in request headers:

// Input token
{ "traceId": "trace-abc-123", "clientVersion": "2.5.0" }

// Headers with interpolation
"headers": {
  "Content-Type": "application/json",
  "X-Trace-Id": "${input.data.traceId}",
  "X-Client-Version": "${input.data.clientVersion}"
}

Request Body Interpolation

Build complex JSON request bodies from token data:

// Input token
{ "customerId": "CUST-001", "total": "599.99", "priority": "high" }

// Body template with nested structure
"body": {
  "order": {
    "customerId": "${input.data.customerId}",
    "total": "${input.data.total}"
  },
  "shipping": {
    "method": "express",
    "priority": "${input.data.priority}"
  },
  "metadata": {
    "timestamp": "${now}",
    "requestId": "${requestId}"
  }
}

Token Metadata in Requests

Include source token metadata for traceability:

// Headers with token metadata
"headers": {
  "X-Token-Id": "${input._meta.id}",
  "X-Token-Name": "${input._meta.name}"
},

// Body with source tracking
"body": {
  "payload": "${input.data.payload}",
  "sourceTokenId": "${input._meta.id}",
  "sourceTokenName": "${input._meta.name}"
}

Available metadata:

  • ${input._meta.id} – Token UUID
  • ${input._meta.name} – Token name
  • ${input._meta.parentId} – Parent place UUID

Authentication

HTTP transitions support multiple authentication methods:

Basic Authentication

Username and password encoded as Base64:

{
  "action": {
    "type": "http",
    "method": "GET",
    "url": "https://api.example.com/protected",
    "auth": {
      "type": "basic",
      "username": "testuser",
      "password": "testpass"
    }
  }
}

This automatically adds the Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M= header.

Bearer Token Authentication

For OAuth2 or JWT-based authentication:

{
  "action": {
    "type": "http",
    "method": "POST",
    "url": "https://api.example.com/data",
    "auth": {
      "type": "bearer",
      "token": "eyJhbGciOiJIUzI1NiIs..."
    }
  }
}

This adds the Authorization: Bearer eyJhbGciOiJIUzI1NiIs... header.

API Key Authentication

For services that use API keys in headers:

{
  "action": {
    "type": "http",
    "method": "GET",
    "url": "https://api.example.com/data",
    "auth": {
      "type": "api_key",
      "headerName": "X-Api-Key",
      "apiKey": "secret-api-key-xyz"
    }
  }
}

This adds the custom header X-Api-Key: secret-api-key-xyz.

Retry Logic and Error Handling

HTTP transitions include robust retry capabilities for handling transient failures:

{
  "action": {
    "type": "http",
    "method": "POST",
    "url": "https://api.example.com/orders",
    "retry": {
      "maxAttempts": 3,
      "backoffMs": 1000,
      "backoffMultiplier": 2.0,
      "retryOn": ["5xx", "429", "io"]
    }
  }
}

Retry configuration options:

Option Description Default
maxAttempts Maximum number of retry attempts 3
backoffMs Initial backoff delay in milliseconds 1000
backoffMultiplier Multiplier for exponential backoff 2.0
retryOn Conditions that trigger retry [“5xx”, “429”]

Retry conditions:

  • "5xx" – Retry on server errors (500-599)
  • "429" – Retry on rate limiting
  • "io" – Retry on network I/O errors

Error Handling Behavior

Important: When an HTTP call fails (4xx, 5xx, timeout, or exhausted retries), the input token is preserved – it is NOT consumed. This enables:

  • Manual retry by re-firing the transition
  • Dead letter queue patterns (move failed tokens to error place)
  • Automatic retry when the transition fires again
// After HTTP error:
// - Input token remains in input place (not consumed)
// - Error emit rules are NOT processed
// - Token available for re-processing

Timeout Configuration

Configure per-request timeouts to handle slow endpoints:

{
  "action": {
    "type": "http",
    "method": "GET",
    "url": "https://api.example.com/slow-endpoint",
    "timeoutMs": 30000  // 30 seconds
  }
}

If the request exceeds the timeout, it’s treated as an error and the input token is preserved for retry.

Response Routing

Route HTTP responses to different postsets based on success or failure:

Success/Error Routing

{
  "postsets": {
    "success": { "placeId": "success-queue", "host": "myModel@localhost:8080" },
    "error": { "placeId": "error-queue", "host": "myModel@localhost:8080" }
  },

  "emit": [
    { "to": "success", "from": "@response.json", "when": "success" },
    { "to": "error", "from": "@input.data", "when": "error" }
  ]
}

Emit conditions:

  • "when": "success" – Emit on HTTP 2xx responses
  • "when": "error" – Emit on HTTP errors (see note below)

Note: In the current implementation, error emit rules are only processed for responses that reach the response processing stage. HTTP errors (4xx, 5xx, timeouts) that throw exceptions preserve the input token without processing emit rules.

Multi-Emit on Success

Send successful responses to multiple destinations:

{
  "postsets": {
    "processed": { "placeId": "processed-queue", "host": "myModel@localhost:8080" },
    "audit": { "placeId": "audit-log", "host": "myModel@localhost:8080" }
  },

  "emit": [
    { "to": "processed", "from": "@response.json", "when": "success" },
    { "to": "audit", "from": "@response.meta", "when": "success" }
  ]
}

Emit Payloads

HTTP transitions offer multiple payload options for emit rules:

@response.json – Full Response Body

Emit the entire JSON response from the HTTP call:

// HTTP response
{
  "orderId": "ORD-123",
  "status": "created",
  "createdAt": "2024-01-15T10:30:00Z"
}

// Emit rule
{ "to": "output", "from": "@response.json", "when": "success" }

// Token created in output place
{
  "orderId": "ORD-123",
  "status": "created",
  "createdAt": "2024-01-15T10:30:00Z",
  "_transitionId": "t-my-api",
  "_status": "success",
  "_emittedAt": "2024-01-15T10:30:01Z"
}

@response.meta – Response Metadata

Emit HTTP metadata instead of the body:

// Emit rule
{ "to": "metrics", "from": "@response.meta", "when": "success" }

// Token created with HTTP metadata
{
  "status": "200",
  "url": "https://api.example.com/orders",
  "durationMs": "245",
  "_transitionId": "t-my-api",
  "_status": "success",
  "_emittedAt": "2024-01-15T10:30:01Z"
}

Use case: Performance monitoring, SLA tracking, audit logging.

@input.data – Original Token Data

Emit the original input token (useful for error paths):

// Input token
{ "orderId": "ORD-123", "customerId": "CUST-456" }

// Emit rule for error path
{ "to": "retry-queue", "from": "@input.data", "when": "error" }

// Original token preserved in retry queue
{ "orderId": "ORD-123", "customerId": "CUST-456" }

Automatic Features

Correlation ID Injection

Every HTTP request automatically includes an X-Correlation-Id header for distributed tracing:

// Automatic header added to every request
"X-Correlation-Id": "8a769e7d-ea8f-4286-9a82-bc9aeba4dabe"

This correlation ID can be used to trace requests across your entire system, from AgenticOS through downstream services.

Built-in Variables

In addition to token data, these built-in variables are available:

  • ${requestId} – Unique request UUID (same as correlation ID)
  • ${now} – Current timestamp in ISO 8601 format

Pattern 1: Simple API Call with Response Routing

Basic pattern for calling an API and routing the response:

{
  "id": "t-fetch-order",
  "kind": "task",
  "mode": "SINGLE",

  "presets": {
    "input": {
      "placeId": "order-requests",
      "host": "orders@localhost:8080",
      "arcql": "FROM $ LIMIT 1",
      "take": "FIRST",
      "consume": true
    }
  },

  "postsets": {
    "output": { "placeId": "order-data", "host": "orders@localhost:8080" }
  },

  "action": {
    "type": "http",
    "method": "GET",
    "url": "https://api.example.com/orders/${input.data.orderId}",
    "timeoutMs": 30000
  },

  "emit": [
    { "to": "output", "from": "@response.json", "when": "success" }
  ]
}

Pattern 2: Authenticated POST with Retry

Create resources with authentication and retry logic:

{
  "id": "t-create-order",
  "kind": "task",
  "mode": "SINGLE",

  "presets": {
    "input": {
      "placeId": "new-orders",
      "host": "orders@localhost:8080",
      "arcql": "FROM $ LIMIT 1",
      "take": "FIRST",
      "consume": true
    }
  },

  "postsets": {
    "created": { "placeId": "created-orders", "host": "orders@localhost:8080" },
    "failed": { "placeId": "failed-orders", "host": "orders@localhost:8080" }
  },

  "action": {
    "type": "http",
    "method": "POST",
    "url": "https://api.example.com/orders",
    "headers": { "Content-Type": "application/json" },
    "body": {
      "customerId": "${input.data.customerId}",
      "items": "${input.data.items}",
      "total": "${input.data.total}"
    },
    "auth": {
      "type": "bearer",
      "token": "your-api-token"
    },
    "timeoutMs": 30000,
    "retry": {
      "maxAttempts": 3,
      "backoffMs": 1000,
      "backoffMultiplier": 2.0,
      "retryOn": ["5xx", "429"]
    }
  },

  "emit": [
    { "to": "created", "from": "@response.json", "when": "success" }
  ]
}

Pattern 3: Multi-Emit for Audit Logging

Send response to processing queue AND audit log:

{
  "id": "t-audited-api-call",
  "kind": "task",
  "mode": "SINGLE",

  "presets": {
    "input": {
      "placeId": "requests",
      "host": "myModel@localhost:8080",
      "arcql": "FROM $ LIMIT 1",
      "take": "FIRST",
      "consume": true
    }
  },

  "postsets": {
    "json-output": { "placeId": "responses", "host": "myModel@localhost:8080" },
    "meta-output": { "placeId": "metrics", "host": "myModel@localhost:8080" }
  },

  "action": {
    "type": "http",
    "method": "GET",
    "url": "https://api.example.com/data?id=${input.data.id}",
    "timeoutMs": 30000
  },

  "emit": [
    { "to": "json-output", "from": "@response.json", "when": "success" },
    { "to": "meta-output", "from": "@response.meta", "when": "success" }
  ]
}

This creates two tokens on success:

  1. responses – Contains the full JSON response body
  2. metrics – Contains HTTP metadata (status, duration, URL)

Pattern 4: Webhook Integration

Post events to external webhooks:

{
  "id": "t-webhook-notify",
  "kind": "task",
  "mode": "SINGLE",

  "presets": {
    "input": {
      "placeId": "events",
      "host": "notifications@localhost:8080",
      "arcql": "FROM $ LIMIT 1",
      "take": "FIRST",
      "consume": true
    }
  },

  "postsets": {
    "delivered": { "placeId": "delivered", "host": "notifications@localhost:8080" }
  },

  "action": {
    "type": "http",
    "method": "POST",
    "url": "https://webhook.example.com/events",
    "headers": {
      "Content-Type": "application/json",
      "X-Webhook-Secret": "shared-secret-key"
    },
    "body": {
      "event": "${input.data.eventType}",
      "payload": "${input.data.payload}",
      "timestamp": "${now}",
      "correlationId": "${requestId}"
    },
    "timeoutMs": 10000
  },

  "emit": [
    { "to": "delivered", "from": "@response.meta", "when": "success" }
  ]
}

Best Practices

1. Always Set Timeouts

Never rely on default timeouts. Set explicit timeoutMs values appropriate for each endpoint:

"timeoutMs": 30000  // 30 seconds for most APIs
"timeoutMs": 60000  // 60 seconds for slow operations
"timeoutMs": 5000   // 5 seconds for health checks

2. Configure Appropriate Retry Strategies

Match retry configuration to the API characteristics:

// For idempotent operations (GET, PUT, DELETE)
"retry": { "maxAttempts": 3, "retryOn": ["5xx", "429", "io"] }

// For non-idempotent operations (POST) - be cautious
"retry": { "maxAttempts": 1 }  // Or use idempotency keys

3. Include Traceability Headers

Add token metadata to requests for debugging:

"headers": {
  "X-Token-Id": "${input._meta.id}",
  "X-Token-Name": "${input._meta.name}",
  "X-Source-Transition": "t-my-transition"
}

4. Use @response.meta for Monitoring

Emit response metadata to a metrics place for SLA monitoring:

"emit": [
  { "to": "response-data", "from": "@response.json", "when": "success" },
  { "to": "api-metrics", "from": "@response.meta", "when": "success" }
]

5. Secure Credential Management

Never hardcode credentials in inscriptions. Use environment variables or secret management:

// Token-based credentials (recommended)
{ "apiKey": "${input.data.apiKey}" }

// Or use service-level configuration
// Configure credentials in agentic-net-master application.properties

HTTP vs Map vs Pass: When to Use Each

Use Case Pass Map HTTP
Simple token routing Yes
Filter/gate based on data Yes
Transform token structure Yes
Add computed fields Yes
Call external REST API Yes
Send webhooks Yes
Integrate microservices Yes
Fetch external data Yes

Complete Working Example

Here’s a complete HTTP transition that fetches order details, adds authentication, handles errors, and routes responses:

{
  "id": "t-order-enrichment",
  "kind": "task",
  "mode": "SINGLE",

  "presets": {
    "input": {
      "placeId": "pending-orders",
      "host": "orders@localhost:8080",
      "arcql": "FROM $ WHERE $.status==\"pending\" LIMIT 1",
      "take": "FIRST",
      "consume": true
    }
  },

  "postsets": {
    "enriched": { "placeId": "enriched-orders", "host": "orders@localhost:8080" },
    "metrics": { "placeId": "api-metrics", "host": "orders@localhost:8080" }
  },

  "action": {
    "type": "http",
    "method": "GET",
    "url": "https://api.example.com/orders/${input.data.orderId}/details",
    "headers": {
      "Accept": "application/json",
      "X-Request-Id": "${requestId}",
      "X-Source-Token": "${input._meta.id}"
    },
    "auth": {
      "type": "api_key",
      "headerName": "X-Api-Key",
      "apiKey": "your-api-key"
    },
    "timeoutMs": 30000,
    "retry": {
      "maxAttempts": 3,
      "backoffMs": 1000,
      "backoffMultiplier": 2.0,
      "retryOn": ["5xx", "429"]
    }
  },

  "emit": [
    { "to": "enriched", "from": "@response.json", "when": "success" },
    { "to": "metrics", "from": "@response.meta", "when": "success" }
  ]
}

This transition:

  1. Reads pending orders from pending-orders place
  2. Calls external API with order ID from token
  3. Includes API key authentication
  4. Adds correlation and source tracking headers
  5. Retries up to 3 times on server errors
  6. On success: sends response body to enriched-orders
  7. On success: sends metadata to api-metrics for monitoring
  8. On error: preserves input token for retry

Summary

HTTP transitions are the integration backbone of Agentic Nets, enabling your agentic processes to communicate with any HTTP endpoint. With template interpolation, multiple authentication methods, retry logic, and flexible response routing, you can build robust integrations entirely through declarative JSON inscriptions.

Key takeaways:

  • Template interpolation everywhere – URLs, headers, and bodies all support ${...} expressions
  • Multiple auth methods – Basic, Bearer, and API Key authentication built-in
  • Robust error handling – Configurable retries with exponential backoff
  • Token preservation on error – Failed requests don’t consume input tokens
  • Flexible emit payloads – Choose between @response.json, @response.meta, or @input.data
  • Automatic correlation – Every request includes X-Correlation-Id for tracing
  • Token metadata access – Include source token info in requests for traceability

Combined with Pass transitions for routing, Map transitions for transformation, and HTTP transitions for external integration, you have a complete toolkit for building sophisticated, maintainable agent orchestration in Agentic Nets.

Leave a Reply

Your email address will not be published. Required fields are marked *