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
- Response Mapping: the inbound direction, transforming API responses to RDF
- RDF Functions: ValueFunction, JSONFunction, and RDFFunction in detail
- Service Integration Actions: handler configuration, healing, reconciliation
- Security: declaring the secrets that request templates resolve