Developer GuidesActionsService Integrations

Request Mapping

Building request templates that transform graph data into outbound HTTP requests.

Request templates define how a service integration action constructs its outbound HTTP request. They map data from the invocation context (subject properties, payload fields, resolved secrets) into HTTP method, path, headers, and body. This guide covers the components of request templates, how dynamic values are computed, and common patterns for authentication, paths, and request bodies.

How Request Templates Work

When RARS executes a service integration action, it materializes the request template into a concrete HTTP request. The template is a declarative specification: you define what the request should look like, and RARS handles the transport, retry, timeout, and error handling.

A request template is composed of rars-act:requestObjectMap entries, each defining one aspect of the request (method, path, a header, the body). Static values are used directly. Dynamic values are computed at runtime using RDF Functions.

Common Components

Request templates are built from composable pieces.

Auth Headers

Most APIs need authentication. Here's a Bearer token auth header:

# Bearer token: "Bearer " + resolved API key
tasks:BearerAuthHeader
    a rars-os:RDFFunction ;
    rars-os:executesFunction grel:string_concat ;
    rars-os:functionInput [
        rars-os:functionParameter grel:valueParameter ;
        rars-os:functionInputValue "Bearer "
    ] ;
    rars-os:functionInput [
        rars-os:functionParameter grel:valueParameter2 ;
        rars-os:functionInputValue [
            a rars-os:RDFFunction ;
            rars-os:executesFunction rars-scrt:resolve_secret ;
            rars-os:functionInput [
                rars-os:functionParameter rars-scrt:secret ;
                rars-os:functionInputValue tasks:TaskServiceAPIKey
            ]
        ]
    ] .

This composes two functions: resolve the secret, then prepend "Bearer ". At runtime, RARS evaluates bottom-up. The secret is never exposed in the graph; rars-scrt:resolve_secret produces a marker string that RARS replaces with the actual value only when constructing the HTTP request.

For APIs that use a simple API key header (no prefix):

tasks:APIKeyHeader
    a rars-os:RDFFunction ;
    rars-os:executesFunction rars-scrt:resolve_secret ;
    rars-os:functionInput [
        rars-os:functionParameter rars-scrt:secret ;
        rars-os:functionInputValue tasks:TaskServiceAPIKey
    ] .

For Basic auth:

tasks:BasicAuthHeader
    a rars-os:RDFFunction ;
    rars-os:executesFunction grel:string_concat ;
    rars-os:functionInput [
        rars-os:functionParameter grel:valueParameter ;
        rars-os:functionInputValue "Basic "
    ] ;
    rars-os:functionInput [
        rars-os:functionParameter grel:valueParameter2 ;
        rars-os:functionInputValue [
            a rars-os:RDFFunction ;
            rars-os:executesFunction rars-scrt:resolve_secret ;
            rars-os:functionInput [
                rars-os:functionParameter rars-scrt:secret ;
                rars-os:functionInputValue tasks:BasicAuthCredential
            ]
        ]
    ] .

Dynamic Paths

A value function extracts a path from the invocation context:

tasks:TaskIdPath
    a rars-os:ValueFunction ;
    rars-os:datatype xsd:string ;
    rars-os:fromValue """
    PREFIX tasks: <https://example.org/spec/tasks#>
    PREFIX rars-act:   <https://poliglot.io/rars/spec/actions#>
    PREFIX rars-os:    <https://poliglot.io/rars/spec/os#>
    SELECT ?value WHERE {
        ?_process rars-os:parent ?invocation .
        ?invocation rars-act:subject ?subject .
        ?subject tasks:externalId ?id .
        BIND(CONCAT("/api/tasks/", STR(?id)) AS ?value)
    }
    """ .

For endpoints with multiple dynamic segments:

tasks:WorkspaceTaskPath
    a rars-os:ValueFunction ;
    rars-os:datatype xsd:string ;
    rars-os:fromValue """
    PREFIX tasks:     <https://example.org/spec/tasks#>
    PREFIX rars-ws: <https://poliglot.io/rars/spec/workspace#>
    PREFIX rars-act:       <https://poliglot.io/rars/spec/actions#>
    PREFIX rars-os:        <https://poliglot.io/rars/spec/os#>
    SELECT ?value WHERE {
        ?_process rars-os:parent ?invocation .
        ?invocation rars-act:subject ?subject .
        ?subject tasks:externalId ?taskId .
        ?subject tasks:workspace ?ws .
        ?ws rars-ws:slug ?slug .
        BIND(CONCAT("/workspaces/", STR(?slug), "/tasks/", STR(?taskId)) AS ?value)
    }
    """ .

Request Object Maps

Individual request object maps can also be named for reuse across templates. Define header maps that every request to the same API shares:

tasks:AuthorizationHeader
    a rars-act:RequestObjectMap ;
    rars-act:predicate rars-http:hasHeader ;
    rars-act:objectMap [
        rars-act:objectMap [ rars-act:predicate rars-http:headerName ; rars-act:value "Authorization" ] ;
        rars-act:objectMap [ rars-act:predicate rars-http:headerValue ; rars-act:value tasks:BearerAuthHeader ]
    ] .

tasks:JsonContentType
    a rars-act:RequestObjectMap ;
    rars-act:predicate rars-http:hasHeader ;
    rars-act:objectMap [
        rars-act:objectMap [ rars-act:predicate rars-http:headerName ; rars-act:value "Content-Type" ] ;
        rars-act:objectMap [ rars-act:predicate rars-http:headerValue ; rars-act:value "application/json" ]
    ] .

Composing Templates

With named building blocks defined, the templates themselves become clean and readable:

Simple GET

tasks:ListTasksRequest
    a rars-act:RequestTemplate ;
    rars-act:requestObjectMap [ rars-act:predicate rars-http:method ; rars-act:value "GET" ] ;
    rars-act:requestObjectMap [ rars-act:predicate rars-http:path ; rars-act:value "/api/tasks" ] ;
    rars-act:requestObjectMap tasks:AuthorizationHeader .

GET with Dynamic Path

tasks:GetTaskRequest
    a rars-act:RequestTemplate ;
    rars-act:requestObjectMap [ rars-act:predicate rars-http:method ; rars-act:value "GET" ] ;
    rars-act:requestObjectMap [ rars-act:predicate rars-http:path ; rars-act:value tasks:TaskIdPath ] ;
    rars-act:requestObjectMap tasks:AuthorizationHeader .

POST with JSON Body

tasks:CreateTaskRequest
    a rars-act:RequestTemplate ;
    rars-act:requestObjectMap [ rars-act:predicate rars-http:method ; rars-act:value "POST" ] ;
    rars-act:requestObjectMap [ rars-act:predicate rars-http:path ; rars-act:value "/api/tasks" ] ;
    rars-act:requestObjectMap tasks:AuthorizationHeader ;
    rars-act:requestObjectMap tasks:JsonContentType ;
    rars-act:requestObjectMap [
        rars-act:predicate rars-http:body ;
        rars-act:value tasks:CreateTaskBody
    ] .

Each template is a short list of components. The complexity lives in the named building blocks, not in nested anonymous structures.

JSON Request Bodies

Use rars-os:fromJSON to construct a JSON body from the invocation payload:

tasks:CreateTaskBody
    a rars-os:JSONFunction ;
    rars-os:fromJSON """
    PREFIX tasks: <https://example.org/spec/tasks#>
    PREFIX rars-act:   <https://poliglot.io/rars/spec/actions#>
    PREFIX rars-os:    <https://poliglot.io/rars/spec/os#>
    JSON {
        "title": ?title,
        "description": ?desc,
        "priority": ?priority
    } WHERE {
        ?_process rars-os:parent ?invocation .
        ?invocation rars-act:payload ?p .
        ?p tasks:title ?title .
        ?p tasks:description ?desc .
        ?p tasks:priority ?priority .
    }
    """ .

Optional Fields

Use SPARQL's OPTIONAL for payload fields that may not be present. Unbound variables are omitted from the JSON output:

tasks:UpdateTaskBody
    a rars-os:JSONFunction ;
    rars-os:fromJSON """
    PREFIX tasks: <https://example.org/spec/tasks#>
    PREFIX rars-act:   <https://poliglot.io/rars/spec/actions#>
    PREFIX rars-os:    <https://poliglot.io/rars/spec/os#>
    JSON {
        "title": ?title,
        "status": ?status,
        "assignee_id": ?assigneeId
    } WHERE {
        ?_process rars-os:parent ?invocation .
        ?invocation rars-act:payload ?p .
        OPTIONAL { ?p tasks:title ?title }
        OPTIONAL { ?p tasks:status ?status }
        OPTIONAL { ?p tasks:assigneeId ?assigneeId }
    }
    """ .

Nested JSON Objects

For APIs that expect nested structures, use nested JSON blocks:

claude:ChatRequestBody
    a rars-os:JSONFunction ;
    rars-os:fromJSON """
    PREFIX rars-ai: <https://poliglot.io/rars/spec/genai#>
    PREFIX rars-act:   <https://poliglot.io/rars/spec/actions#>
    PREFIX rars-os:    <https://poliglot.io/rars/spec/os#>
    JSON {
        "model": ?model,
        "max_tokens": ?maxTokens,
        "messages": [{
            "role": ?role,
            "content": ?content
        }] WHERE {
            ?invocation rars-act:payload ?p .
            ?p rars-ai:hasMessage ?msg .
            ?msg rars-ai:role ?role .
            ?msg rars-ai:content ?content .
        }
    } WHERE {
        ?_process rars-os:parent ?invocation .
        ?invocation rars-act:subject ?subject .
        ?subject rars-ai:modelId ?model .
        ?invocation rars-act:payload ?p .
        ?p rars-ai:maxTokens ?maxTokens .
    }
    """ .

The inner JSON [...] block produces an array by iterating over its own WHERE clause. This constructs {"model": "claude-sonnet-4-5-20250929", "max_tokens": 1024, "messages": [{"role": "user", "content": "Hello"}]}.

DELETE Requests

DELETE requests typically need only a method, path, and auth:

tasks:DeleteTaskRequest
    a rars-act:RequestTemplate ;
    rars-act:requestObjectMap [ rars-act:predicate rars-http:method ; rars-act:value "DELETE" ] ;
    rars-act:requestObjectMap [ rars-act:predicate rars-http:path ; rars-act:value tasks:TaskIdPath ] ;
    rars-act:requestObjectMap tasks:AuthorizationHeader .

Components like tasks:TaskIdPath and tasks:AuthorizationHeader can be shared across GET, PUT, and DELETE templates for the same API.

Design Guidance

Match the API's Contract

Map your payload fields to the external API's expected field names exactly. Don't normalize or transform on the way out unless the API requires it. Save transformation for the response mapping where you control the target schema.

Secret Safety

Secrets resolved via rars-scrt:resolve_secret are never exposed in the graph. The function produces a marker string that RARS replaces with the actual value only at HTTP request construction time. The AI never sees API keys, tokens, or credentials during reasoning.

See Also

On this page