Block Agent API Components
This guide describes important components to understand when interacting with a Block Agent via API. Learn more about:
Overview
Whether you're building a voice assistant integrated with a telephony platform, a chatbot embedded in a website, or a backend service orchestrating complex workflows, understanding the Block Agent API components is essential.
Use this guide to learn more about how to call agents, how to pass data into them, and how to interpret the rich responses they return.
Getting Started
Before you being using any AI API make sure you have a username and password with API access created under the specific account you want to use the APIs with. Your Block Agent should be build under this same account.
Using the API access username and password, you should also generate a JWT Bearer token via API request to use with the AI APIs.
POST Authentication Request
POST https://atmosphere-api.intelepeer.com/rest/v1/authenticate
Your token appears in the "data" section of the response.
Base URL
All of the following AI endpoints share the same base URL:
Production URL
https://aiservice.intelepeer.com
Sample Endpoint
POST https://aiservice.intelepeer.com/aihub/v2/agent/abc123/response?customer_id=cust456&session_id=sess789&enhanced=true
Enhanced Query Parameter
If you're using the v2 APIs, you must include the enhanced=true query parameter to access all of the features below.
This parameter enables features like Jinja templating, updated context management, and MCP server tooling.
Sample Request with the Enhanced Parameter
POST https://aiservice.intelepeer.com/aihub/v2/agent/abc123/response?customer_id=cust456&session_id=sess789&enhanced=true
Note: If you are using the v3 APIs, the enhanced=true flag is no longer needed as these features are enabled by default.
Request Body
You can provide the user's input, pass contextual data, and configure agent behavior within the request body.
Sample Request Body
{
"user_message": "hi, i would like to schedule",
"flow_args": {
"arg_context_date_time": "Todays date: Friday 2025-11-07 and Current time is 10:00 AM",
"arg_context_date": "2025-11-07",
"arg_context": "Phone: 123-456-7890. Office Hours: Monday from 8am – 7pm Eastern",
"arg_ANI": "123-456-7891"
},
"policy": {
"office_name": "Dr. Teeth Main Street",
"transfer_number": "+11234567892",
"enable_spanish": true
}
}
You'll notice the following important components included in the sample request body:
Check out the respective sections below for more information.
User Message
The user_message field contains what the user said. This is the primary input that drives the conversation forward.
Standard Input
For typical conversational Turns, this is a simple string from ASR (Automatic Speech Recognition):
{
"user_message": "I need to schedule a cleaning appointment"
}
Wait Turn
For Wait Turns, the user_message carries structured data from external systems.
Sample Wait Turn User Message
{
"user_message": {
"success": true,
"date_of_birth_lookup": "schedule_appointment",
"patient_id": "P12345",
"data": {
"patient_name": "John Smith",
"existing_appointments": [
{
"date": "2025-01-20T14:00:00",
"type": "cleaning"
}
]
}
}
}
Remember:
-
Top-level fields (success, date_of_birth_lookup in our sample above) are transient. Available for Edge evaluation in the current Turn.
-
While data.* fields are persistent. They are accessible across subsequent Turns via data.patient_name, data.existing_appointments, etc. in our sample above.
Flow Arguments
The flow_args object passes contextual information that applies only to the current Turn. These values are transient, meaning they exist for this request only and won't persist to subsequent Turns unless you pass them again.
Sample Flow Arguments
{
"flow_args": {
"arg_context_date_time": "Todays date: Friday 2025-11-07 and Current time is 10:00 AM",
"arg_context_date": "2025-11-07",
"arg_context": "Phone: 123-456-7890. Office Hours: Monday 8am–7pm Eastern. FAQs: ...",
"arg_ANI": "123-456-7891",
"arg_is_existing_patient": true,
"arg_ani_match": {
"patient_id": "P12345",
"date_of_birth": "1985-06-15",
"first_name": "John"
}
}
}
Frequently Used Arguments
| Argument | Purpose | Sample |
|---|---|---|
| arg_context_date_time | Current date/time for scheduling logic | "Friday 2025-11-07 10:00 AM" |
| arg_context_date | ISO date for calculations | "2025-11-07" |
| arg_context | FAQs, office info, knowledge base content | "Office Hours: Mon-Fri 8am-5pm..." |
| arg_ANI | Caller's phone number | "123-456-7890" |
| arg_ani_match | Caller lookup result from CRM | { "patient_id": "P123", ... } |
| arg_existing_appointments | Pre-fetched appointment data | { "matches": [...] } |
| arg_appointment_types | Available appointment types | { "appointment_types": [...] } |
Accessing Flow Arguments in Turns
Inside your Turn content, these become available as Jinja2 variables:
content: |-
{% if arg_ani_match is defined and arg_ani_match %}
Welcome back, {{ arg_ani_match.first_name }}!
I see you have an upcoming appointment.
{% else %}
Hello! How can I help you today?
{% endif %}
Current date and time: {{ arg_context_date_time }}
Transient variables are ideal for:
-
Information that changes every Turn (current time, latest lookup results)
-
Data that should be refreshed on each call
-
Context that isn't relevant across the full session
Policy
The policy object contains configuration that persists for the entire session. Unlike flow_args, you typically send policies once at the start of a conversation, and they remain available for all subsequent turns.
Sample Policy
{
"policy": {
"office_name": "Dr. Teeth Main Street",
"office_id": "LOC001",
"transfer_number": "+11234567892",
"enable_spanish": true,
"max_booking_days_ahead": 30,
"allowed_appointment_types": ["cleaning", "consultation", "emergency"],
"business_rules": {
"require_insurance": false,
"allow_same_day": false
}
}
}
Policies are:
-
Persistent: Survive across all Turns in the session.
-
Updatable: Sending a policy in a later Turn updates values.
-
Session-Scoped: Cleared when the session ends.
-
Accessible: Available in Turns, Tools, and Edge Conditions.
Accessing Policies in Turns
Sample Policy
content: |-
You're calling {{ policy.office_name }}.
{% if policy.enable_spanish %}
(Spanish support is available)
{% endif %}
{% if policy.business_rules.allow_same_day %}
I can schedule same-day appointments.
{% else %}
Please note that same-day appointments are not available.
{% endif %}
When to Use Policies vs. Flow Arguments
| Scenario | Recommendation | Reasoning |
|---|---|---|
| Office configuration | policy | Doesn't change during the call. |
| Current date/time | flow_arg | Changes each Turn. |
| Caller lookup results | flow_arg | May need fresh data. |
| Transfer numbers | policy | Static configuration. |
| Available services | policy | Session-wide setting. |
| Real-time availability | flow_args | Must be current. |
API Response
When the agent processes your request, it returns a comprehensive response containing the conversational output, extracted data, and debugging information. Understanding this response is crucial for building robust integrations.
Response Structure
{
"ai_response": "string",
"ai_split_responses": ["string"],
"output": {},
"debug": {},
"ai_output": {}
}
Sample Response
{
"ai_response": "Is this appointment for a new patient?",
"ai_split_responses": [
" Is this appointment for a new patient?"
],
"output": {
"is_schedule_appointment": true,
"schedule_appointment": true,
"intent_utterance": "hi, i would like to schedule",
"is_language_detected": true,
"language_detected": true,
"language_name": "English"
},
"ai_output": {
"is_tool_call": true,
"tools": {
"triggered": [
"is_schedule_appointment",
"is_language_detected"
],
"is_schedule_appointment": {
"schedule_appointment": true,
"intent_utterance": "hi, i would like to schedule"
},
"is_language_detected": {
"language_detected": true,
"language_name": "English"
}
},
"block_id": "000000",
"block_name": "Greeting_Intent",
"turn_id": "000005",
"turn_name": "greeting_intent",
"looping_threshold": false,
"next_block_id": "000001",
"next_block_name": "Greeting_Intent",
"next_turn_id": "000010",
"next_turn_name": null,
"turn_loop_count": 1,
"executed_turns": [
"000005"
],
"global_tracker": [
"000005"
]
}
}
You'll notice the following important components included in the sample response:
Check out the respective sections below for more information.
AI Response
This is the primary field your application needs, the natural language response that should be spoken or displayed to the user.
{
"ai_response": "Is this appointment for a new patient?"
}
Usage:
-
Send to TTS (Text-to-Speech) for voice applications
-
Display in chat interface for web/mobile apps
-
Log for analytics and quality assurance
Characteristics:
-
Always a string
-
Generated by the LLM based on turn instructions
-
Follows personality guidelines defined in agent configuration
-
Formatted for the medium (voice-friendly for phone, may include formatting for chat)
AI Split Responses
Note: This field is being phased out and should not be relied upon for new implementations.
This array contains the ai_response split into separate sentences:
{
"ai_split_responses": [
" Is this appointment for a new patient?"
]
}
Originally designed for TTS systems that process sentence-by-sentence, this field is no longer recommended. Use ai_response directly instead.
Output
The output object is a cumulative collection of all structured data captured during the session. It builds up over the entire conversation, persisting data from Tool calls, Edge transitions, and explicit data capture.
{
"output": {
"is_schedule_appointment": true,
"schedule_appointment": true,
"intent_utterance": "hi, i would like to schedule",
"is_language_detected": true,
"language_detected": true,
"language_name": "English"
}
}
Characteristics:
-
Cumulative: Builds up over the entire conversation
-
Persistent: Data remains available across Blocks and Turns
-
Structured: Organized as key-value pairs
-
Tool-Integrated: Automatically populated from tool results
Sample Across Three Turns
Turn 1 (Greeting):
output: {
"schedule_appointment": true,
"language_name": "English"
}
Turn 2 (Authentication):
output: {
"schedule_appointment": true,
"language_name": "English",
"date_of_birth": "1985-06-15", // Added
"patient_status": "returning" // Added
}
Turn 3 (Scheduling):
output: {
"schedule_appointment": true,
"language_name": "English",
"date_of_birth": "1985-06-15",
"patient_status": "returning",
"appointment_type": "cleaning", // Added
"appointment_date": "2025-01-20" // Added
}
AI Output
The ai_output object contains detailed information about the current Turn only. This is invaluable for debugging, analytics, and understanding exactly what happened during the interaction.
Sample AI Output
{
"ai_output": {
"is_tool_call": true,
"tools": {
"triggered": [
"is_schedule_appointment",
"is_language_detected"
],
"is_schedule_appointment": {
"schedule_appointment": true,
"intent_utterance": "hi, i would like to schedule"
},
"is_language_detected": {
"language_detected": true,
"language_name": "English"
}
},
"block_id": "000000",
"block_name": "Greeting_Intent",
"turn_id": "000005",
"turn_name": "greeting_intent",
"looping_threshold": false,
"next_block_id": "000001",
"next_block_name": "Greeting_Intent",
"next_turn_id": "000010",
"next_turn_name": null,
"turn_loop_count": 1,
"executed_turns": [
"000005"
],
"global_tracker": [
"000005"
]
}
}
Key Components
|
Component |
Description |
|---|---|
|
is_tool_call |
Whether any tools were triggered this Turn |
|
tools.triggered |
Array of Tool names that were executed |
|
tools.[tool_name] |
Individual Tool results and extracted data |
|
block_id |
Identifier of the current Block |
|
block_name |
Human-readable name of current Block |
|
turn_id |
Identifier of the current Turn |
|
turn_name |
Human-readable name of current Turn |
|
looping_threshold |
Boolean indicating if max loops reached |
|
next_turn_id |
Identifier of the next Turn to execute |
|
next_turn_name |
Human-readable name of next Turn |
|
turn_loop_count |
How many times this Turn has looped |
|
executed_turns |
Array of all Turn IDs executed in session |
|
global_tracker |
Similar to executed_turns; tracks cross-agent jumps |
The Global Tracker Component vs. Executed Turns Component
Both fields track executed Turns, but they serve different purposes:
|
Component |
Scope |
Scenario |
|---|---|---|
|
executed_turns |
Current agent |
Tracking flow within one agent |
|
global_tracker |
Cross-agent |
Tracking when agents call other agents (reusable components) |
The global_tracker becomes essential when working with reusable agent components, where one agent can invoke another as a sub-routine.