Orchestrata Ultimate / Specs / 067-remote-trigger-tool

067-remote-trigger-tool: RemoteTriggerTool - Remote Webhook/API Trigger

A tool that triggers remote webhooks or API calls with support for various authentication methods, request/response handling, retry logic, and result validation.

At a glance

Item Value
Spec directory specs/067-remote-trigger-tool/
Status line in the spec Complete
Requirement IDs defined 23
With a @traces citation in src/ 23 (100.0%)
With a @traces citation in tests/ 0 (0.0%)
Tracked files 3
RTM page 067-remote-trigger-tool

Reading this spec

This spec defines RemoteTriggerTool, a tool that fires remote webhooks and calls third-party APIs, so agents can integrate with external services, trigger automated workflows (such as a CI/CD pipeline), take part in event-driven architectures and chain multi-step API calls. It handles authentication, request and response processing, retries and result validation.

Three user stories give the scope: a CI/CD pipeline trigger, external service integration and multi-step API chaining. The design is an HTTP/HTTPS client with connection pooling, several authentication schemes (API key, bearer token, basic auth, OAuth2 and HMAC), request and response transformation, retry with exponential backoff, and webhook signature verification. The functional requirements (FR-001 onward) cover HTTP request execution, authentication support, request configuration, retry logic, response validation and timeout handling.

The 23 requirement IDs (REQ-067-NNN) pin down the details. Requests use GET, POST, PUT, PATCH, DELETE, HEAD or OPTIONS with configurable headers, body and query parameters. A numeric Retry-After response header sets the delay before the next attempt. Response validation uses a lightweight JSON Schema subset (type, required, properties and items). The connection pool is a configurable httpx.Limits pool scoped to one execute call. Logs record method, sanitized URL, status, elapsed time and retry count, and sensitive headers are sanitized in them. A public verify_signature method checks a payload against a signature, secret and algorithm.

The implementation is in the remote trigger tool module. The requirements traceability matrix lists each ID. The spec's own status line reads Complete and it tracks 3 files. Measured coverage is 23 of 23 requirements cited by at least one @traces in src/ (100.0%), spread over 1 module; the module citing the most of them is orchestrata_ultimate/tools/remote_trigger_tool (23 requirements). In tests/, 0 requirements are cited by a test-side @traces, so test-side citations are thinner than code-side ones.

Requirements

Checkbox is the state recorded in the requirements checklist; Traced by is the count of src/ symbols whose @traces names the ID.

ID Done Requirement Traced by
REQ-067-001 yes Execute HTTP requests (GET/POST/PUT/PATCH/DELETE/HEAD/OPTIONS) to a configured URL with configurable headers/body. 8
REQ-067-002 yes API Key authentication, placed in a header or a query parameter (in: header|query). 4
REQ-067-003 yes Bearer Token authentication, literal or resolved from an env var (token_env). 5
REQ-067-004 yes Basic authentication (Base64-encoded username:password, password literal or password_env). 3
REQ-067-005 yes OAuth2 client-credentials token fetch (POST to token_url, resulting access_token used as Bearer). Token-refresh/caching lifecycle deferred (MVP: one fetch per request). 3
REQ-067-006 yes HMAC request signing (sha256/sha512/sha1) — computes a signature over the request body and injects it as a configurable header, secret literal or secret_env. 5
REQ-067-007 yes Configurable HTTP method, custom headers, request body (JSON object/array or raw string), and query parameters. 3
REQ-067-008 yes Configurable max attempts, exponential backoff (initial_delay * backoff_factor ** attempt, capped at max_delay), and configurable retryable status codes. 4
REQ-067-009 yes Retry on request timeout (retry_on_timeout). 3
REQ-067-010 yes Respects a numeric Retry-After response header (ERR-005) as the next-attempt delay. 4
REQ-067-011 yes Validate against expected HTTP status codes (defaults to 2xx when unset). 4
REQ-067-012 yes Validate response-time thresholds (min_response_time/max_response_time). 3
REQ-067-013 yes JSON Schema validation — lightweight subset (type/required/properties/items; no format/pattern/enum/$ref, no external jsonschema dependency). 5
REQ-067-014 yes Webhook HMAC signature verification (verify_signature + ValidationConfig.signature_secret(_env)). 4
REQ-067-015 yes Configurable per-request timeout with a clear timeout error message ("Request timeout after {n} seconds"). 2
REQ-067-016 yes Configurable httpx.Limits connection pool (connection_pool_size), scoped to the lifetime of one execute/execute_simple call (see module docstring fork note — no cross-call persistent client). 2
REQ-067-017 yes SSL verification enabled by default; custom CA bundle path (ca_bundle_path) supported; disabling verification (verify_ssl=false) logs a warning. 2
REQ-067-018 yes Parses JSON responses (content-type aware, falls back to raw text) and extracts dotted-path fields (extract_fields) into the response. Response-format conversion (e.g. XML->JSON) deferred. 6
REQ-067-019 yes Logs request/response (method, sanitized URL, status, elapsed ms, retry count) and sanitizes sensitive headers (Authorization, X-API-Key) before any debug-level header log. 3
REQ-067-020 yes Blocks outbound requests to loopback/private/link-local/reserved addresses and known metadata hostnames/IPs (single-resolution check via socket.getaddrinfo), overridable per-request (allow_internal) or via REMOTE_TRIGGER_ALLOW_PRIVATE (read at call time). DNS-rebinding protection and an allowlist are deferred. 5
REQ-067-021 yes execute_simple(url, method, headers, body, auth, timeout, env) simplified interface. 2
REQ-067-022 yes verify_signature(payload, signature, secret, algorithm) public method. 3
REQ-067-023 yes ERR-00N conditions (invalid URL, auth failure, forbidden, not found, rate limited, server error, timeout, connection error, SSL error, invalid signature, retry exhausted, invalid config, DNS failure) surfaced as RemoteTriggerError/TriggerResponse.error with the spec.md wording. 5

Code that traces this spec

Module Symbols Requirements
orchestrata_ultimate/tools/remote_trigger_tool 43 23

Checklists

checklists/requirements.md

The requirement list above comes from this file; 23 of 23 checkbox items are ticked.

Other tracked files

Full spec text

Verbatim from specs/067-remote-trigger-tool/spec.md; headings are pushed down two levels.

SPEC-067: RemoteTriggerTool - Remote Webhook/API Trigger

Metadata


Overview

What

A tool that triggers remote webhooks or API calls with support for various authentication methods, request/response handling, retry logic, and result validation.

Why
How

User Scenarios

US-001: CI/CD Pipeline Trigger

As a DevOps engineer
I want to trigger a GitHub Actions workflow remotely
So that I can automate deployments when code is pushed to a branch

Acceptance Criteria:

US-002: External Service Integration

As a application developer
I want to notify external services via webhooks
So that I can integrate with third-party systems and external workflows

Acceptance Criteria:

US-003: Multi-Step API Chaining

As a workflow orchestrator
I want to chain multiple API calls with polling for results
So that I can manage long-running processes and dependent tasks

Acceptance Criteria:


Terminology

Core Concepts
Key Components

Data Models

JSON Schemas
TriggerRequest
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "TriggerRequest",
  "type": "object",
  "required": ["url", "method"],
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "description": "Target webhook or API endpoint URL"
    },
    "method": {
      "type": "string",
      "enum": ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"],
      "description": "HTTP method"
    },
    "headers": {
      "type": "object",
      "additionalProperties": {"type": "string"},
      "description": "Custom headers"
    },
    "body": {
      "type": ["object", "string", "number", "boolean", "array", "null"],
      "description": "Request body (for POST, PUT, PATCH)"
    },
    "auth": {
      "$ref": "#/definitions/AuthConfig"
    },
    "timeout": {
      "type": "integer",
      "minimum": 1,
      "maximum": 300,
      "default": 30,
      "description": "Request timeout in seconds"
    },
    "retry": {
      "$ref": "#/definitions/RetryConfig"
    },
    "validation": {
      "$ref": "#/definitions/ValidationConfig"
    }
  },
  "definitions": {
    "AuthConfig": {
      "type": "object",
      "oneOf": [
        {"$ref": "#/definitions/ApiKeyAuth"},
        {"$ref": "#/definitions/BearerAuth"},
        {"$ref": "#/definitions/BasicAuth"},
        {"$ref": "#/definitions/OAuth2Auth"},
        {"$ref": "#/definitions/HmacAuth"}
      ]
    },
    "ApiKeyAuth": {
      "type": "object",
      "required": ["type", "key", "value"],
      "properties": {
        "type": {"const": "api_key"},
        "key": {"type": "string"},
        "value": {"type": "string"},
        "in": {"type": "string", "enum": ["header", "query"]}
      }
    },
    "BearerAuth": {
      "type": "object",
      "required": ["type", "token"],
      "properties": {
        "type": {"const": "bearer"},
        "token": {"type": "string"},
        "token_env": {"type": "string", "description": "Environment variable name for token"}
      }
    },
    "BasicAuth": {
      "type": "object",
      "required": ["type", "username"],
      "properties": {
        "type": {"const": "basic"},
        "username": {"type": "string"},
        "password": {"type": "string"},
        "password_env": {"type": "string", "description": "Environment variable name for password"}
      }
    },
    "OAuth2Auth": {
      "type": "object",
      "required": ["type", "client_id", "token_url"],
      "properties": {
        "type": {"const": "oauth2"},
        "client_id": {"type": "string"},
        "client_secret": {"type": "string"},
        "client_secret_env": {"type": "string"},
        "token_url": {"type": "string", "format": "uri"},
        "scopes": {"type": "array", "items": {"type": "string"}},
        "grant_type": {"type": "string", "enum": ["client_credentials", "password"]}
      }
    },
    "HmacAuth": {
      "type": "object",
      "required": ["type", "secret", "algorithm"],
      "properties": {
        "type": {"const": "hmac"},
        "secret": {"type": "string"},
        "secret_env": {"type": "string"},
        "algorithm": {"type": "string", "enum": ["sha256", "sha512", "sha1"]},
        "header_name": {"type": "string", "default": "X-Signature"}
      }
    },
    "RetryConfig": {
      "type": "object",
      "properties": {
        "enabled": {"type": "boolean", "default": true},
        "max_attempts": {"type": "integer", "minimum": 1, "maximum": 10, "default": 3},
        "initial_delay": {"type": "number", "minimum": 0.1, "default": 1.0},
        "max_delay": {"type": "number", "minimum": 1, "default": 60.0},
        "backoff_factor": {"type": "number", "minimum": 1, "default": 2.0},
        "retry_on_status": {"type": "array", "items": {"type": "integer"}, "default": [429, 500, 502, 503, 504]}
      }
    },
    "ValidationConfig": {
      "type": "object",
      "properties": {
        "expected_status": {"type": "array", "items": {"type": "integer"}},
        "min_response_time": {"type": "number", "description": "Minimum expected response time in seconds"},
        "max_response_time": {"type": "number", "description": "Maximum allowed response time in seconds"},
        "schema": {"type": "object", "description": "JSON schema to validate response against"},
        "signature_secret": {"type": "string", "description": "Secret for webhook signature verification"},
        "signature_header": {"type": "string", "default": "X-Signature"}
      }
    }
  }
}
TriggerResponse
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "TriggerResponse",
  "type": "object",
  "required": ["success", "status_code", "timestamp"],
  "properties": {
    "success": {"type": "boolean"},
    "status_code": {"type": "integer"},
    "status_text": {"type": "string"},
    "timestamp": {"type": "string", "format": "date-time"},
    "elapsed_ms": {"type": "integer"},
    "headers": {"type": "object", "additionalProperties": {"type": "string"}},
    "body": {},
    "validation_passed": {"type": "boolean"},
    "validation_errors": {"type": "array", "items": {"type": "string"}},
    "retry_count": {"type": "integer"},
    "error": {"type": "string"}
  }
}
WebhookEvent
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "WebhookEvent",
  "type": "object",
  "required": ["id", "source", "timestamp"],
  "properties": {
    "id": {"type": "string", "format": "uuid"},
    "source": {"type": "string"},
    "timestamp": {"type": "string", "format": "date-time"},
    "payload": {"type": "object"},
    "headers": {"type": "object", "additionalProperties": {"type": "string"}},
    "signature_valid": {"type": "boolean"}
  }
}

Functional Requirements

FR-001: HTTP Request Execution

The tool MUST execute HTTP requests to specified URLs with configurable method, headers, and body.

FR-002: Authentication Support

The tool MUST support multiple authentication methods:

FR-003: Request Configuration

The tool MUST allow configuration of:

FR-004: Retry Logic

The tool MUST implement configurable retry logic with:

FR-005: Response Validation

The tool MUST validate responses against:

FR-006: Timeout Handling

The tool MUST handle timeouts gracefully with:

FR-007: Connection Pooling

The tool MUST implement connection pooling for:

FR-008: SSL/TLS Verification

The tool MUST:

FR-009: Response Transformation

The tool MUST support response transformation:

FR-010: Logging and Auditing

The tool MUST:

FR-011: Webhook Signature Verification

The tool MUST verify webhook signatures:


Error Conditions

ID Condition Handling
ERR-001 Invalid URL Reject with 400 status and "Invalid or malformed URL: {url}"
ERR-002 Authentication Failure Report 401 status with "Authentication failed: {reason}"
ERR-003 Forbidden Access Report 403 status with "Access forbidden to {url}"
ERR-004 Endpoint Not Found Report 404 status with "Endpoint not found: {url}"
ERR-005 Rate Limiting Handle 429 status with "Rate limit exceeded. Retry after {retry_after} seconds"
ERR-006 Server Error Report 5xx status with "Server error: {status_code}"
ERR-007 Timeout Report "Request timeout after {timeout} seconds"
ERR-008 Connection Error Report "Failed to connect to {host}: {reason}"
ERR-009 SSL Verification Failed Report "SSL certificate verification failed: {reason}"
ERR-010 Invalid Response Report "Response validation failed: {validation_error}"
ERR-011 Invalid Signature Report "Webhook signature verification failed"
ERR-012 Retry Exhausted Report "Max retry attempts ({max_attempts}) exceeded"
ERR-013 Invalid Configuration Report "Configuration error: {detail}"
ERR-014 Body Too Large Report 413 status with "Request body exceeds maximum size of {max_size} bytes"
ERR-015 DNS Resolution Failure Report "Failed to resolve DNS for {hostname}"
ERR-016 Invalid JSON Payload Report "Invalid JSON in request body: {error}"
ERR-017 Content Type Mismatch Report "Unexpected content type: {content_type}"

API Contracts

Tool Interface
class RemoteTriggerTool(BaseTool):
    """Trigger remote webhooks and API calls."""
    
    name = "remote_trigger"
    description = "Trigger remote webhooks or API calls with authentication"
    
    async def execute(
        self,
        request: TriggerRequest
    ) -> TriggerResponse:
        """Execute a remote trigger request."""
        
    async def execute_simple(
        self,
        url: str,
        method: str = "POST",
        headers: dict = None,
        body: dict = None,
        auth: AuthConfig = None,
        timeout: int = 30
    ) -> TriggerResponse:
        """Simplified interface for basic triggers."""
        
    async def verify_signature(
        self,
        payload: bytes,
        signature: str,
        secret: str,
        algorithm: str = "sha256"
    ) -> bool:
        """Verify webhook signature."""
        
    async def parse_response(
        self,
        response: Response,
        validation: ValidationConfig = None
    ) -> dict:
        """Parse and validate response."""
Configuration Schema
class RemoteTriggerConfig(BaseModel):
    """Tool configuration."""
    
    timeout_default: int = Field(default=30, ge=1, le=300)
    max_retries: int = Field(default=3, ge=0, le=10)
    retry_backoff_factor: float = Field(default=2.0, ge=1.0)
    connection_pool_size: int = Field(default=10, ge=1, le=100)
    verify_ssl: bool = True
    ca_bundle_path: str = None
    default_headers: dict = {}
    log_requests: bool = True
    sensitive_headers: list[str] = ["Authorization", "X-API-Key"]
Public Methods
Method Parameters Returns Description
execute request: TriggerRequest TriggerResponse Execute trigger with full config
execute_simple url, method, headers, body, auth, timeout TriggerResponse Simplified trigger
verify_signature payload, signature, secret, algorithm bool Verify HMAC signature
parse_response response, validation dict Parse and validate response

Non-Functional Requirements

Performance
Reliability
Scalability
Security
Maintainability

Technical Design

Architecture Overview

The RemoteTriggerTool follows a layered architecture:

┌─────────────────────────────────────────┐
│           RemoteTriggerTool             │
├─────────────────────────────────────────┤
│  ┌─────────┐ ┌─────────┐ ┌──────────┐  │
│  │  Auth   │ │  Retry  │ │  Validate│  │
│  │ Manager │ │  Logic  │ │   Module │  │
│  └─────────┘ └─────────┘ └──────────┘  │
├─────────────────────────────────────────┤
│         HTTP Client (httpx)             │
├─────────────────────────────────────────┤
│      Connection Pool Manager            │
└─────────────────────────────────────────┘
Core Components
TriggerRequestProcessor
AuthenticationManager
RetryExecutor
ResponseValidator
SSRFProtection
Data Flow
  1. Client calls execute(trigger_request)
  2. Request validation (URL format, auth config, timeout)
  3. AuthManager applies authentication headers
  4. RetryExecutor makes HTTP call with retry logic
  5. ResponseValidator checks response
  6. TriggerResponse returned with results
Extension Points

Examples

remote_trigger:
  defaults:
    timeout: 30
    verify_ssl: true
    max_retries: 3
    retry_backoff_factor: 2.0
    connection_pool_size: 10
  
  auth:
    github:
      type: bearer
      token_env: GITHUB_TOKEN
    
    slack:
      type: api_key
      key: X-Slack-Secret
      value_env: SLACK_SECRET
      in: header
    
    custom_service:
      type: oauth2
      client_id_env: OAUTH_CLIENT_ID
      client_secret_env: OAUTH_CLIENT_SECRET
      token_url: https://auth.example.com/oauth/token
      scopes: ["api:read", "api:write"]
  
  endpoints:
    deployments:
      url: https://api.example.com/deployments
      auth: custom_service
      expected_status: [201, 202]
    
    notifications:
      url: https://hooks.example.com/notify
      auth: slack
      expected_status: [200]

Security Requirements

Authentication
API Key Authentication
Bearer Token Authentication
Basic Authentication
OAuth2 Client Credentials
HMAC Signature
Encryption
Transport Layer
Data at Rest
Result Validation
Status Code Validation
Response Schema Validation
Signature Verification
Input Validation
Audit Logging

Governance

Policy Enforcement
SSRF Protection

The tool MUST implement SSRF protection including:

Rate Limiting Rules
Audit Logging

All remote trigger events MUST be logged including:

async def log_trigger(url: str, result: dict):
    await audit_log({
        "event_type": "remote_trigger",
        "url": sanitize_url(url),
        "method": result.method,
        "status_code": result.status_code,
        "success": result.success,
        "duration_ms": result.duration_ms,
        "agent": get_current_agent()
    })
Governance Rules (Prolog)
% RemoteTriggerTool governance rules

% Allow trigger to non-sensitive endpoints
may_trigger(Agent, Endpoint) :-
    non_sensitive_endpoint(Endpoint),
    has_permission(Agent, webhook_trigger).

% Block trigger to sensitive endpoints without elevated permission
may_trigger(Agent, Endpoint) :-
    sensitive_endpoint(Endpoint),
    has_permission(Agent, webhook_trigger_elevated),
    audit_log(Agent, Endpoint).

% Sensitive endpoint patterns
sensitive_endpoint(Endpoint) :-
    contains(Endpoint, "production"),
    contains(Endpoint, "admin").

% Non-sensitive endpoint patterns  
non_sensitive_endpoint(Endpoint) :-
    not contains(Endpoint, "admin"),
    not contains(Endpoint, "/internal/").

% Rate limiting rules
rate_limit(Agent, Endpoint, Requests) :-
    Requests =< 100,
    time_window(Agent, 60, Requests).

% Require HTTPS for sensitive data
require_https(Endpoint) :-
    contains(Endpoint, "auth"),
    contains(Endpoint, "payment"),
    not contains(Endpoint, "http://localhost").

Dependencies

Runtime Dependencies
Package Version Purpose
httpx >=0.27.0 HTTP client with async support
pydantic >=2.0.0 Data validation
python-jose >=3.3.0 JWT/OAuth2 token handling
cryptography >=41.0.0 HMAC signature generation
Development Dependencies
Package Version Purpose
pytest >=7.0.0 Testing framework
pytest-asyncio >=0.21.0 Async test support
pytest-cov >=4.0.0 Coverage reporting
respx >=0.20.0 HTTP mocking
ruff >=0.1.0 Linting
Optional Dependencies
Package Version Purpose
aiohttp >=3.9.0 Alternative HTTP backend
urllib3 >=2.0.0 Connection pooling

Testing Requirements

Unit Tests
Authentication Tests
Request Execution Tests
Retry Logic Tests
Validation Tests
Integration Tests
Real HTTP Tests
End-to-End Scenarios
Error Handling Tests
Error Condition Tests
Performance Tests

Integration Points

HTTP Client Integration
Authentication Providers
Event Systems
Configuration Management

Success Criteria

Functional Success
Performance Success
Reliability Success
Security Success

Observability

Logging Requirements
  1. Component Logging
    • Log all major operations with appropriate log levels
    • Include correlation IDs for request tracing
    • Log performance metrics for critical operations
    • Log errors with full context for debugging
Metrics Requirements
  1. Performance Metrics
    • Operation duration histograms
    • Request/error rate counters
    • Resource utilization gauges
    • Business metrics relevant to domain
Tracing Requirements
  1. Distributed Tracing
    • Trace propagation across component boundaries
    • Span attributes for domain-specific context
    • Trace sampling based on operational needs
Alerting Requirements
  1. Critical Alerts
    • Error rate spikes
    • Performance degradation
    • Resource exhaustion
    • Business metric anomalies
Dashboard Requirements
  1. Operational Dashboard
    • Real-time system health
    • Performance trends
    • Error analysis
    • Resource monitoring

Revision History

Version Date Author Changes
1.0.0 2026-04-08 Mohamed Initial specification
1.0.1 2026-04-09 Mohamed Fixed spec standard compliance, added missing sections, converted error conditions to table format