Repository files navigation

AI

A Ruby gem for integrating AI agents from Mastra into your Rails application. This gem provides a Rails generator to create and manage AI agents seamlessly within your Ruby applications.

Table of Contents

Overview

This gem provides a bridge between Mastra AI agents and your Rails application. It automatically generates client code for your agents and provides a consistent interface for calling them from your services.

Step-by-Step Guide

1. Create an Agent in Mastra

Before you can use an agent in your Ruby application, you need to create it in Mastra first:

  1. Create a new agent with your desired configuration
  2. Note the agent name (this will be used in the next step)
  3. Ensure the Mastra service is running and accessible

2. Generate the Agent Client

Once your agent is created in Mastra, generate the corresponding Ruby agent using the Rails generator:

# Generate all agents from Mastra
bin/rails generate ai:agent --all

This command will:

  • Fetch the agent configuration from Mastra
  • Generate the corresponding Ruby client file in app/generated/ai/agents/

3. Use the Agent in Your Rails Application

After generating the agent client, you can use it in your Rails application services:

Step 3.1: Define an Output Structure

Create a service that defines an output class using T::Struct:

classMyAgentServiceextendT::Sig# Define the expected output structureclassOutput < T::Structconst:result,Stringconst:confidence,Floatconst:metadata,T::Hash[String,T.untyped],default: {}endsig{params(input: String).returns(Output)}defself.call(input)# Your service logic heremessages=[Ai.user_message(input)]# Initialize the agent (this would typically be done once and reused)agent=Ai::Agent.new(agent_name: 'my_custom_agent',client: Ai::Client.new)# Generate structured outputresult=agent.generate_object(messages: messages,output_class: Output)endend

Step 3.2: Create Appropriate Messages

Structure your messages according to your agent's expected format:

messages=[Ai.system_message("You are a helpful assistant that..."),Ai.user_message("User's question or request")]

Sending Images:

For vision-capable agents, you can include images in your messages:

# Read image from fileimage_data=File.binread('path/to/image.png')# Create a message with text and imagemessage=Ai.user_message_with_image("What objects are in this image?",image_data,"image/png")messages=[message]

For multiple images in one message, use manual construction:

image1=File.binread('photo1.jpg')image2=File.binread('photo2.png')message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images:"),Ai::ImagePart.new(image_data: image1,media_type: "image/jpeg"),Ai::ImagePart.new(image_data: image2,media_type: "image/png")])

Sending documents (e.g. PDFs):

Providers that support file inputs can read documents directly — for PDFs the model sees both the embedded text layer and the rendered pages:

pdf_data=File.binread('path/to/invoice.pdf')message=Ai.user_message_with_file("Extract the invoice fields from this document",pdf_data,"application/pdf",filename: "invoice.pdf")messages=[message]

For custom combinations, Ai::FilePart composes with the other parts the same way Ai::ImagePart does:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these documents:"),Ai::FilePart.new(file_data: pdf1,media_type: "application/pdf",filename: "a.pdf"),Ai::FilePart.new(file_data: pdf2,media_type: "application/pdf",filename: "b.pdf")])

Using Image URLs:

Instead of sending image data, you can send a URL for the agent to fetch the image:

# Create a message with text and image URLmessage=Ai.user_message_with_image_url("What objects are in this image?","https://example.com/photo.jpg","image/jpeg")messages=[message]

For multiple image URLs or mixing URLs with text:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images from the web:"),Ai::ImagePart.new(image_url: "https://example.com/image1.jpg",media_type: "image/jpeg"),Ai::ImagePart.new(image_url: "https://example.com/image2.png",media_type: "image/png")])

Step 3.3: Call the Agent

# Use the service in your applicationresult=MyAgentService.call("What is the weather like today?")putsresult.result# => Agent's responseputsresult.confidence# => Confidence scoreputsresult.metadata# => Additional metadata

Advanced Usage

The generate_object method supports additional options for fine-tuning:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_object(messages: messages,output_class: Output,request_context: {user_id: 123,session: 'abc'},# Optional contextmax_retries: 3,# Retry attempts (default: 2)max_steps: 10# Max processing steps (default: 5))# Access the structured outputoutput=result.objectputsoutput.result

For simple text generation without structured output:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_text(messages: messages,request_context: {},# Optional contextmax_retries: 2,# Retry attempts (default: 2)max_steps: 5# Max processing steps (default: 5))putsresult.text# Generated text response

Telemetry Configuration

The gem supports OpenTelemetry integration for monitoring and observability. You can configure telemetry settings to control what data is recorded and add metadata for better tracing:

Telemetry Options:

  • enabled: Enable/disable telemetry (default: true)
  • record_inputs: Record input messages (default: false, disable for sensitive data)
  • record_outputs: Record output responses (default: false, disable for sensitive data)
  • function_id: Identifier for grouping telemetry data by function
  • metadata: Additional metadata for OpenTelemetry traces (agent identification, service info, etc.)
# Create telemetry settingstelemetry_settings=Ai::TelemetrySettings.new(enabled: true,record_inputs: false,# Disable for sensitive datarecord_outputs: true,# Enable for monitoringfunction_id: 'user-chat-session',metadata: {'agent.name'=>'customer-support','service.name'=>'mastra','service.namespace'=>'customer-service','cx.application.name'=>'ai-tracing','cx.subsystem.name'=>'mastra-agents'})# Use with text generationresult=agent.generate_text(messages: messages,telemetry: telemetry_settings)# Use with structured outputresult=agent.generate_object(messages: messages,output_class: Output,telemetry: telemetry_settings)

Workflows

Mastra "workflows" let you orchestrate multiple agents to solve a task.
The generator creates a lightweight Ruby wrapper that exposes typed Input and Output structs and a convenience .call method.

⚠️ there is no auto-conversion between snake case to pascal case (my_var → myVar) or back.

1. Generate a Workflow Client

# Generate a specific workflow
bin/rails generate ai:workflow --name="testWorkflow"# Generate all workflows present in Mastra
bin/rails generate ai:workflow --all

The generator will create files in app/generated/ai/workflows/.

2. Use the Workflow

input=Ai::Workflows::TestWorkflow::Input.new(first_number: 2.0,second_number: 3.0)# Run the workflowresult=Ai::Workflows::TestWorkflow.call(input)putsresult.sumOfNumbers# => 5.0

Example generated wrapper:

moduleAimoduleWorkflowsclassTestWorkflowextendT::SigclassInput < T::Structconst:first_number,Floatconst:second_number,FloatendclassOutput < T::Structconst:sumOfNumbers,Floatendsig{params(input: Input).returns(Output)}defself.call(input:)response=Ai.client.run_workflow('testWorkflow',input:)TypeCoerce[Output].from(response)rescueTypeCoerce::CoercionError,ArgumentError=>eraiseAi::Error,"Workflow 'testWorkflow' output could not be coerced: #{e.message}"endendendend

Generator Options

Both ai:agent and ai:workflow generators accept the same set of command-line flags:

  • --endpoint URL – Mastra API endpoint URL (default: value from MASTRA_LOCATION environment variable).
  • --all – Generate all agents/workflows found in Mastra.
  • --name NAME – Name of the agent/workflow to generate (required unless --all is provided).
  • --force – Override existing files if they already exist.
  • --output PATH – Output directory for generated files.
    • Agents default: app/generated/ai/agents
    • Workflows default: app/generated/ai/workflows

Generating your agents/workflows

rails generate ai:agent AGENT_NAME [options]rails generate ai:workflow WORKFLOW_NAME [options]

Basic Examples

The same applies for workflows.

# Generate a specific agent
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111
# Generate all agents from Mastra
bin/rails generate ai:agent --all --endpoint http://localhost:4111

Advanced Examples

# Generate with custom output directory
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --output lib/custom/agents
# Force overwrite existing files
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --force
# Generate all agents with custom settings
bin/rails generate ai:agent --all --endpoint http://localhost:4111 --output app/ai/agents --force

About

Ruby AI client to interact with Mastra agents

Resources

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

AI

A Ruby gem for integrating AI agents from Mastra into your Rails application. This gem provides a Rails generator to create and manage AI agents seamlessly within your Ruby applications.

Table of Contents

Overview

This gem provides a bridge between Mastra AI agents and your Rails application. It automatically generates client code for your agents and provides a consistent interface for calling them from your services.

Step-by-Step Guide

1. Create an Agent in Mastra

Before you can use an agent in your Ruby application, you need to create it in Mastra first:

  1. Create a new agent with your desired configuration
  2. Note the agent name (this will be used in the next step)
  3. Ensure the Mastra service is running and accessible

2. Generate the Agent Client

Once your agent is created in Mastra, generate the corresponding Ruby agent using the Rails generator:

# Generate all agents from Mastra
bin/rails generate ai:agent --all

This command will:

  • Fetch the agent configuration from Mastra
  • Generate the corresponding Ruby client file in app/generated/ai/agents/

3. Use the Agent in Your Rails Application

After generating the agent client, you can use it in your Rails application services:

Step 3.1: Define an Output Structure

Create a service that defines an output class using T::Struct:

classMyAgentServiceextendT::Sig# Define the expected output structureclassOutput < T::Structconst:result,Stringconst:confidence,Floatconst:metadata,T::Hash[String,T.untyped],default: {}endsig{params(input: String).returns(Output)}defself.call(input)# Your service logic heremessages=[Ai.user_message(input)]# Initialize the agent (this would typically be done once and reused)agent=Ai::Agent.new(agent_name: 'my_custom_agent',client: Ai::Client.new)# Generate structured outputresult=agent.generate_object(messages: messages,output_class: Output)endend

Step 3.2: Create Appropriate Messages

Structure your messages according to your agent's expected format:

messages=[Ai.system_message("You are a helpful assistant that..."),Ai.user_message("User's question or request")]

Sending Images:

For vision-capable agents, you can include images in your messages:

# Read image from fileimage_data=File.binread('path/to/image.png')# Create a message with text and imagemessage=Ai.user_message_with_image("What objects are in this image?",image_data,"image/png")messages=[message]

For multiple images in one message, use manual construction:

image1=File.binread('photo1.jpg')image2=File.binread('photo2.png')message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images:"),Ai::ImagePart.new(image_data: image1,media_type: "image/jpeg"),Ai::ImagePart.new(image_data: image2,media_type: "image/png")])

Sending documents (e.g. PDFs):

Providers that support file inputs can read documents directly — for PDFs the model sees both the embedded text layer and the rendered pages:

pdf_data=File.binread('path/to/invoice.pdf')message=Ai.user_message_with_file("Extract the invoice fields from this document",pdf_data,"application/pdf",filename: "invoice.pdf")messages=[message]

For custom combinations, Ai::FilePart composes with the other parts the same way Ai::ImagePart does:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these documents:"),Ai::FilePart.new(file_data: pdf1,media_type: "application/pdf",filename: "a.pdf"),Ai::FilePart.new(file_data: pdf2,media_type: "application/pdf",filename: "b.pdf")])

Using Image URLs:

Instead of sending image data, you can send a URL for the agent to fetch the image:

# Create a message with text and image URLmessage=Ai.user_message_with_image_url("What objects are in this image?","https://example.com/photo.jpg","image/jpeg")messages=[message]

For multiple image URLs or mixing URLs with text:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images from the web:"),Ai::ImagePart.new(image_url: "https://example.com/image1.jpg",media_type: "image/jpeg"),Ai::ImagePart.new(image_url: "https://example.com/image2.png",media_type: "image/png")])

Step 3.3: Call the Agent

# Use the service in your applicationresult=MyAgentService.call("What is the weather like today?")putsresult.result# => Agent's responseputsresult.confidence# => Confidence scoreputsresult.metadata# => Additional metadata

Advanced Usage

The generate_object method supports additional options for fine-tuning:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_object(messages: messages,output_class: Output,request_context: {user_id: 123,session: 'abc'},# Optional contextmax_retries: 3,# Retry attempts (default: 2)max_steps: 10# Max processing steps (default: 5))# Access the structured outputoutput=result.objectputsoutput.result

For simple text generation without structured output:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_text(messages: messages,request_context: {},# Optional contextmax_retries: 2,# Retry attempts (default: 2)max_steps: 5# Max processing steps (default: 5))putsresult.text# Generated text response

Telemetry Configuration

The gem supports OpenTelemetry integration for monitoring and observability. You can configure telemetry settings to control what data is recorded and add metadata for better tracing:

Telemetry Options:

  • enabled: Enable/disable telemetry (default: true)
  • record_inputs: Record input messages (default: false, disable for sensitive data)
  • record_outputs: Record output responses (default: false, disable for sensitive data)
  • function_id: Identifier for grouping telemetry data by function
  • metadata: Additional metadata for OpenTelemetry traces (agent identification, service info, etc.)
# Create telemetry settingstelemetry_settings=Ai::TelemetrySettings.new(enabled: true,record_inputs: false,# Disable for sensitive datarecord_outputs: true,# Enable for monitoringfunction_id: 'user-chat-session',metadata: {'agent.name'=>'customer-support','service.name'=>'mastra','service.namespace'=>'customer-service','cx.application.name'=>'ai-tracing','cx.subsystem.name'=>'mastra-agents'})# Use with text generationresult=agent.generate_text(messages: messages,telemetry: telemetry_settings)# Use with structured outputresult=agent.generate_object(messages: messages,output_class: Output,telemetry: telemetry_settings)

Workflows

Mastra "workflows" let you orchestrate multiple agents to solve a task.
The generator creates a lightweight Ruby wrapper that exposes typed Input and Output structs and a convenience .call method.

⚠️ there is no auto-conversion between snake case to pascal case (my_var → myVar) or back.

1. Generate a Workflow Client

# Generate a specific workflow
bin/rails generate ai:workflow --name="testWorkflow"# Generate all workflows present in Mastra
bin/rails generate ai:workflow --all

The generator will create files in app/generated/ai/workflows/.

2. Use the Workflow

input=Ai::Workflows::TestWorkflow::Input.new(first_number: 2.0,second_number: 3.0)# Run the workflowresult=Ai::Workflows::TestWorkflow.call(input)putsresult.sumOfNumbers# => 5.0

Example generated wrapper:

moduleAimoduleWorkflowsclassTestWorkflowextendT::SigclassInput < T::Structconst:first_number,Floatconst:second_number,FloatendclassOutput < T::Structconst:sumOfNumbers,Floatendsig{params(input: Input).returns(Output)}defself.call(input:)response=Ai.client.run_workflow('testWorkflow',input:)TypeCoerce[Output].from(response)rescueTypeCoerce::CoercionError,ArgumentError=>eraiseAi::Error,"Workflow 'testWorkflow' output could not be coerced: #{e.message}"endendendend

Generator Options

Both ai:agent and ai:workflow generators accept the same set of command-line flags:

  • --endpoint URL – Mastra API endpoint URL (default: value from MASTRA_LOCATION environment variable).
  • --all – Generate all agents/workflows found in Mastra.
  • --name NAME – Name of the agent/workflow to generate (required unless --all is provided).
  • --force – Override existing files if they already exist.
  • --output PATH – Output directory for generated files.
    • Agents default: app/generated/ai/agents
    • Workflows default: app/generated/ai/workflows

Generating your agents/workflows

rails generate ai:agent AGENT_NAME [options]rails generate ai:workflow WORKFLOW_NAME [options]

Basic Examples

The same applies for workflows.

# Generate a specific agent
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111
# Generate all agents from Mastra
bin/rails generate ai:agent --all --endpoint http://localhost:4111

Advanced Examples

# Generate with custom output directory
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --output lib/custom/agents
# Force overwrite existing files
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --force
# Generate all agents with custom settings
bin/rails generate ai:agent --all --endpoint http://localhost:4111 --output app/ai/agents --force

About

Ruby AI client to interact with Mastra agents

Resources

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

AI

A Ruby gem for integrating AI agents from Mastra into your Rails application. This gem provides a Rails generator to create and manage AI agents seamlessly within your Ruby applications.

Table of Contents

Overview

This gem provides a bridge between Mastra AI agents and your Rails application. It automatically generates client code for your agents and provides a consistent interface for calling them from your services.

Step-by-Step Guide

1. Create an Agent in Mastra

Before you can use an agent in your Ruby application, you need to create it in Mastra first:

  1. Create a new agent with your desired configuration
  2. Note the agent name (this will be used in the next step)
  3. Ensure the Mastra service is running and accessible

2. Generate the Agent Client

Once your agent is created in Mastra, generate the corresponding Ruby agent using the Rails generator:

# Generate all agents from Mastra
bin/rails generate ai:agent --all

This command will:

  • Fetch the agent configuration from Mastra
  • Generate the corresponding Ruby client file in app/generated/ai/agents/

3. Use the Agent in Your Rails Application

After generating the agent client, you can use it in your Rails application services:

Step 3.1: Define an Output Structure

Create a service that defines an output class using T::Struct:

classMyAgentServiceextendT::Sig# Define the expected output structureclassOutput < T::Structconst:result,Stringconst:confidence,Floatconst:metadata,T::Hash[String,T.untyped],default: {}endsig{params(input: String).returns(Output)}defself.call(input)# Your service logic heremessages=[Ai.user_message(input)]# Initialize the agent (this would typically be done once and reused)agent=Ai::Agent.new(agent_name: 'my_custom_agent',client: Ai::Client.new)# Generate structured outputresult=agent.generate_object(messages: messages,output_class: Output)endend

Step 3.2: Create Appropriate Messages

Structure your messages according to your agent's expected format:

messages=[Ai.system_message("You are a helpful assistant that..."),Ai.user_message("User's question or request")]

Sending Images:

For vision-capable agents, you can include images in your messages:

# Read image from fileimage_data=File.binread('path/to/image.png')# Create a message with text and imagemessage=Ai.user_message_with_image("What objects are in this image?",image_data,"image/png")messages=[message]

For multiple images in one message, use manual construction:

image1=File.binread('photo1.jpg')image2=File.binread('photo2.png')message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images:"),Ai::ImagePart.new(image_data: image1,media_type: "image/jpeg"),Ai::ImagePart.new(image_data: image2,media_type: "image/png")])

Sending documents (e.g. PDFs):

Providers that support file inputs can read documents directly — for PDFs the model sees both the embedded text layer and the rendered pages:

pdf_data=File.binread('path/to/invoice.pdf')message=Ai.user_message_with_file("Extract the invoice fields from this document",pdf_data,"application/pdf",filename: "invoice.pdf")messages=[message]

For custom combinations, Ai::FilePart composes with the other parts the same way Ai::ImagePart does:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these documents:"),Ai::FilePart.new(file_data: pdf1,media_type: "application/pdf",filename: "a.pdf"),Ai::FilePart.new(file_data: pdf2,media_type: "application/pdf",filename: "b.pdf")])

Using Image URLs:

Instead of sending image data, you can send a URL for the agent to fetch the image:

# Create a message with text and image URLmessage=Ai.user_message_with_image_url("What objects are in this image?","https://example.com/photo.jpg","image/jpeg")messages=[message]

For multiple image URLs or mixing URLs with text:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images from the web:"),Ai::ImagePart.new(image_url: "https://example.com/image1.jpg",media_type: "image/jpeg"),Ai::ImagePart.new(image_url: "https://example.com/image2.png",media_type: "image/png")])

Step 3.3: Call the Agent

# Use the service in your applicationresult=MyAgentService.call("What is the weather like today?")putsresult.result# => Agent's responseputsresult.confidence# => Confidence scoreputsresult.metadata# => Additional metadata

Advanced Usage

The generate_object method supports additional options for fine-tuning:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_object(messages: messages,output_class: Output,request_context: {user_id: 123,session: 'abc'},# Optional contextmax_retries: 3,# Retry attempts (default: 2)max_steps: 10# Max processing steps (default: 5))# Access the structured outputoutput=result.objectputsoutput.result

For simple text generation without structured output:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_text(messages: messages,request_context: {},# Optional contextmax_retries: 2,# Retry attempts (default: 2)max_steps: 5# Max processing steps (default: 5))putsresult.text# Generated text response

Telemetry Configuration

The gem supports OpenTelemetry integration for monitoring and observability. You can configure telemetry settings to control what data is recorded and add metadata for better tracing:

Telemetry Options:

  • enabled: Enable/disable telemetry (default: true)
  • record_inputs: Record input messages (default: false, disable for sensitive data)
  • record_outputs: Record output responses (default: false, disable for sensitive data)
  • function_id: Identifier for grouping telemetry data by function
  • metadata: Additional metadata for OpenTelemetry traces (agent identification, service info, etc.)
# Create telemetry settingstelemetry_settings=Ai::TelemetrySettings.new(enabled: true,record_inputs: false,# Disable for sensitive datarecord_outputs: true,# Enable for monitoringfunction_id: 'user-chat-session',metadata: {'agent.name'=>'customer-support','service.name'=>'mastra','service.namespace'=>'customer-service','cx.application.name'=>'ai-tracing','cx.subsystem.name'=>'mastra-agents'})# Use with text generationresult=agent.generate_text(messages: messages,telemetry: telemetry_settings)# Use with structured outputresult=agent.generate_object(messages: messages,output_class: Output,telemetry: telemetry_settings)

Workflows

Mastra "workflows" let you orchestrate multiple agents to solve a task.
The generator creates a lightweight Ruby wrapper that exposes typed Input and Output structs and a convenience .call method.

⚠️ there is no auto-conversion between snake case to pascal case (my_var → myVar) or back.

1. Generate a Workflow Client

# Generate a specific workflow
bin/rails generate ai:workflow --name="testWorkflow"# Generate all workflows present in Mastra
bin/rails generate ai:workflow --all

The generator will create files in app/generated/ai/workflows/.

2. Use the Workflow

input=Ai::Workflows::TestWorkflow::Input.new(first_number: 2.0,second_number: 3.0)# Run the workflowresult=Ai::Workflows::TestWorkflow.call(input)putsresult.sumOfNumbers# => 5.0

Example generated wrapper:

moduleAimoduleWorkflowsclassTestWorkflowextendT::SigclassInput < T::Structconst:first_number,Floatconst:second_number,FloatendclassOutput < T::Structconst:sumOfNumbers,Floatendsig{params(input: Input).returns(Output)}defself.call(input:)response=Ai.client.run_workflow('testWorkflow',input:)TypeCoerce[Output].from(response)rescueTypeCoerce::CoercionError,ArgumentError=>eraiseAi::Error,"Workflow 'testWorkflow' output could not be coerced: #{e.message}"endendendend

Generator Options

Both ai:agent and ai:workflow generators accept the same set of command-line flags:

  • --endpoint URL – Mastra API endpoint URL (default: value from MASTRA_LOCATION environment variable).
  • --all – Generate all agents/workflows found in Mastra.
  • --name NAME – Name of the agent/workflow to generate (required unless --all is provided).
  • --force – Override existing files if they already exist.
  • --output PATH – Output directory for generated files.
    • Agents default: app/generated/ai/agents
    • Workflows default: app/generated/ai/workflows

Generating your agents/workflows

rails generate ai:agent AGENT_NAME [options]rails generate ai:workflow WORKFLOW_NAME [options]

Basic Examples

The same applies for workflows.

# Generate a specific agent
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111
# Generate all agents from Mastra
bin/rails generate ai:agent --all --endpoint http://localhost:4111

Advanced Examples

# Generate with custom output directory
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --output lib/custom/agents
# Force overwrite existing files
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --force
# Generate all agents with custom settings
bin/rails generate ai:agent --all --endpoint http://localhost:4111 --output app/ai/agents --force

About

Ruby AI client to interact with Mastra agents

Resources

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

AI

A Ruby gem for integrating AI agents from Mastra into your Rails application. This gem provides a Rails generator to create and manage AI agents seamlessly within your Ruby applications.

Table of Contents

Overview

This gem provides a bridge between Mastra AI agents and your Rails application. It automatically generates client code for your agents and provides a consistent interface for calling them from your services.

Step-by-Step Guide

1. Create an Agent in Mastra

Before you can use an agent in your Ruby application, you need to create it in Mastra first:

  1. Create a new agent with your desired configuration
  2. Note the agent name (this will be used in the next step)
  3. Ensure the Mastra service is running and accessible

2. Generate the Agent Client

Once your agent is created in Mastra, generate the corresponding Ruby agent using the Rails generator:

# Generate all agents from Mastra
bin/rails generate ai:agent --all

This command will:

  • Fetch the agent configuration from Mastra
  • Generate the corresponding Ruby client file in app/generated/ai/agents/

3. Use the Agent in Your Rails Application

After generating the agent client, you can use it in your Rails application services:

Step 3.1: Define an Output Structure

Create a service that defines an output class using T::Struct:

classMyAgentServiceextendT::Sig# Define the expected output structureclassOutput < T::Structconst:result,Stringconst:confidence,Floatconst:metadata,T::Hash[String,T.untyped],default: {}endsig{params(input: String).returns(Output)}defself.call(input)# Your service logic heremessages=[Ai.user_message(input)]# Initialize the agent (this would typically be done once and reused)agent=Ai::Agent.new(agent_name: 'my_custom_agent',client: Ai::Client.new)# Generate structured outputresult=agent.generate_object(messages: messages,output_class: Output)endend

Step 3.2: Create Appropriate Messages

Structure your messages according to your agent's expected format:

messages=[Ai.system_message("You are a helpful assistant that..."),Ai.user_message("User's question or request")]

Sending Images:

For vision-capable agents, you can include images in your messages:

# Read image from fileimage_data=File.binread('path/to/image.png')# Create a message with text and imagemessage=Ai.user_message_with_image("What objects are in this image?",image_data,"image/png")messages=[message]

For multiple images in one message, use manual construction:

image1=File.binread('photo1.jpg')image2=File.binread('photo2.png')message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images:"),Ai::ImagePart.new(image_data: image1,media_type: "image/jpeg"),Ai::ImagePart.new(image_data: image2,media_type: "image/png")])

Sending documents (e.g. PDFs):

Providers that support file inputs can read documents directly — for PDFs the model sees both the embedded text layer and the rendered pages:

pdf_data=File.binread('path/to/invoice.pdf')message=Ai.user_message_with_file("Extract the invoice fields from this document",pdf_data,"application/pdf",filename: "invoice.pdf")messages=[message]

For custom combinations, Ai::FilePart composes with the other parts the same way Ai::ImagePart does:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these documents:"),Ai::FilePart.new(file_data: pdf1,media_type: "application/pdf",filename: "a.pdf"),Ai::FilePart.new(file_data: pdf2,media_type: "application/pdf",filename: "b.pdf")])

Using Image URLs:

Instead of sending image data, you can send a URL for the agent to fetch the image:

# Create a message with text and image URLmessage=Ai.user_message_with_image_url("What objects are in this image?","https://example.com/photo.jpg","image/jpeg")messages=[message]

For multiple image URLs or mixing URLs with text:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images from the web:"),Ai::ImagePart.new(image_url: "https://example.com/image1.jpg",media_type: "image/jpeg"),Ai::ImagePart.new(image_url: "https://example.com/image2.png",media_type: "image/png")])

Step 3.3: Call the Agent

# Use the service in your applicationresult=MyAgentService.call("What is the weather like today?")putsresult.result# => Agent's responseputsresult.confidence# => Confidence scoreputsresult.metadata# => Additional metadata

Advanced Usage

The generate_object method supports additional options for fine-tuning:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_object(messages: messages,output_class: Output,request_context: {user_id: 123,session: 'abc'},# Optional contextmax_retries: 3,# Retry attempts (default: 2)max_steps: 10# Max processing steps (default: 5))# Access the structured outputoutput=result.objectputsoutput.result

For simple text generation without structured output:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_text(messages: messages,request_context: {},# Optional contextmax_retries: 2,# Retry attempts (default: 2)max_steps: 5# Max processing steps (default: 5))putsresult.text# Generated text response

Telemetry Configuration

The gem supports OpenTelemetry integration for monitoring and observability. You can configure telemetry settings to control what data is recorded and add metadata for better tracing:

Telemetry Options:

  • enabled: Enable/disable telemetry (default: true)
  • record_inputs: Record input messages (default: false, disable for sensitive data)
  • record_outputs: Record output responses (default: false, disable for sensitive data)
  • function_id: Identifier for grouping telemetry data by function
  • metadata: Additional metadata for OpenTelemetry traces (agent identification, service info, etc.)
# Create telemetry settingstelemetry_settings=Ai::TelemetrySettings.new(enabled: true,record_inputs: false,# Disable for sensitive datarecord_outputs: true,# Enable for monitoringfunction_id: 'user-chat-session',metadata: {'agent.name'=>'customer-support','service.name'=>'mastra','service.namespace'=>'customer-service','cx.application.name'=>'ai-tracing','cx.subsystem.name'=>'mastra-agents'})# Use with text generationresult=agent.generate_text(messages: messages,telemetry: telemetry_settings)# Use with structured outputresult=agent.generate_object(messages: messages,output_class: Output,telemetry: telemetry_settings)

Workflows

Mastra "workflows" let you orchestrate multiple agents to solve a task.
The generator creates a lightweight Ruby wrapper that exposes typed Input and Output structs and a convenience .call method.

⚠️ there is no auto-conversion between snake case to pascal case (my_var → myVar) or back.

1. Generate a Workflow Client

# Generate a specific workflow
bin/rails generate ai:workflow --name="testWorkflow"# Generate all workflows present in Mastra
bin/rails generate ai:workflow --all

The generator will create files in app/generated/ai/workflows/.

2. Use the Workflow

input=Ai::Workflows::TestWorkflow::Input.new(first_number: 2.0,second_number: 3.0)# Run the workflowresult=Ai::Workflows::TestWorkflow.call(input)putsresult.sumOfNumbers# => 5.0

Example generated wrapper:

moduleAimoduleWorkflowsclassTestWorkflowextendT::SigclassInput < T::Structconst:first_number,Floatconst:second_number,FloatendclassOutput < T::Structconst:sumOfNumbers,Floatendsig{params(input: Input).returns(Output)}defself.call(input:)response=Ai.client.run_workflow('testWorkflow',input:)TypeCoerce[Output].from(response)rescueTypeCoerce::CoercionError,ArgumentError=>eraiseAi::Error,"Workflow 'testWorkflow' output could not be coerced: #{e.message}"endendendend

Generator Options

Both ai:agent and ai:workflow generators accept the same set of command-line flags:

  • --endpoint URL – Mastra API endpoint URL (default: value from MASTRA_LOCATION environment variable).
  • --all – Generate all agents/workflows found in Mastra.
  • --name NAME – Name of the agent/workflow to generate (required unless --all is provided).
  • --force – Override existing files if they already exist.
  • --output PATH – Output directory for generated files.
    • Agents default: app/generated/ai/agents
    • Workflows default: app/generated/ai/workflows

Generating your agents/workflows

rails generate ai:agent AGENT_NAME [options]rails generate ai:workflow WORKFLOW_NAME [options]

Basic Examples

The same applies for workflows.

# Generate a specific agent
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111
# Generate all agents from Mastra
bin/rails generate ai:agent --all --endpoint http://localhost:4111

Advanced Examples

# Generate with custom output directory
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --output lib/custom/agents
# Force overwrite existing files
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --force
# Generate all agents with custom settings
bin/rails generate ai:agent --all --endpoint http://localhost:4111 --output app/ai/agents --force

About

Ruby AI client to interact with Mastra agents

Resources

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

AI

A Ruby gem for integrating AI agents from Mastra into your Rails application. This gem provides a Rails generator to create and manage AI agents seamlessly within your Ruby applications.

Table of Contents

Overview

This gem provides a bridge between Mastra AI agents and your Rails application. It automatically generates client code for your agents and provides a consistent interface for calling them from your services.

Step-by-Step Guide

1. Create an Agent in Mastra

Before you can use an agent in your Ruby application, you need to create it in Mastra first:

  1. Create a new agent with your desired configuration
  2. Note the agent name (this will be used in the next step)
  3. Ensure the Mastra service is running and accessible

2. Generate the Agent Client

Once your agent is created in Mastra, generate the corresponding Ruby agent using the Rails generator:

# Generate all agents from Mastra
bin/rails generate ai:agent --all

This command will:

  • Fetch the agent configuration from Mastra
  • Generate the corresponding Ruby client file in app/generated/ai/agents/

3. Use the Agent in Your Rails Application

After generating the agent client, you can use it in your Rails application services:

Step 3.1: Define an Output Structure

Create a service that defines an output class using T::Struct:

classMyAgentServiceextendT::Sig# Define the expected output structureclassOutput < T::Structconst:result,Stringconst:confidence,Floatconst:metadata,T::Hash[String,T.untyped],default: {}endsig{params(input: String).returns(Output)}defself.call(input)# Your service logic heremessages=[Ai.user_message(input)]# Initialize the agent (this would typically be done once and reused)agent=Ai::Agent.new(agent_name: 'my_custom_agent',client: Ai::Client.new)# Generate structured outputresult=agent.generate_object(messages: messages,output_class: Output)endend

Step 3.2: Create Appropriate Messages

Structure your messages according to your agent's expected format:

messages=[Ai.system_message("You are a helpful assistant that..."),Ai.user_message("User's question or request")]

Sending Images:

For vision-capable agents, you can include images in your messages:

# Read image from fileimage_data=File.binread('path/to/image.png')# Create a message with text and imagemessage=Ai.user_message_with_image("What objects are in this image?",image_data,"image/png")messages=[message]

For multiple images in one message, use manual construction:

image1=File.binread('photo1.jpg')image2=File.binread('photo2.png')message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images:"),Ai::ImagePart.new(image_data: image1,media_type: "image/jpeg"),Ai::ImagePart.new(image_data: image2,media_type: "image/png")])

Sending documents (e.g. PDFs):

Providers that support file inputs can read documents directly — for PDFs the model sees both the embedded text layer and the rendered pages:

pdf_data=File.binread('path/to/invoice.pdf')message=Ai.user_message_with_file("Extract the invoice fields from this document",pdf_data,"application/pdf",filename: "invoice.pdf")messages=[message]

For custom combinations, Ai::FilePart composes with the other parts the same way Ai::ImagePart does:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these documents:"),Ai::FilePart.new(file_data: pdf1,media_type: "application/pdf",filename: "a.pdf"),Ai::FilePart.new(file_data: pdf2,media_type: "application/pdf",filename: "b.pdf")])

Using Image URLs:

Instead of sending image data, you can send a URL for the agent to fetch the image:

# Create a message with text and image URLmessage=Ai.user_message_with_image_url("What objects are in this image?","https://example.com/photo.jpg","image/jpeg")messages=[message]

For multiple image URLs or mixing URLs with text:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images from the web:"),Ai::ImagePart.new(image_url: "https://example.com/image1.jpg",media_type: "image/jpeg"),Ai::ImagePart.new(image_url: "https://example.com/image2.png",media_type: "image/png")])

Step 3.3: Call the Agent

# Use the service in your applicationresult=MyAgentService.call("What is the weather like today?")putsresult.result# => Agent's responseputsresult.confidence# => Confidence scoreputsresult.metadata# => Additional metadata

Advanced Usage

The generate_object method supports additional options for fine-tuning:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_object(messages: messages,output_class: Output,request_context: {user_id: 123,session: 'abc'},# Optional contextmax_retries: 3,# Retry attempts (default: 2)max_steps: 10# Max processing steps (default: 5))# Access the structured outputoutput=result.objectputsoutput.result

For simple text generation without structured output:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_text(messages: messages,request_context: {},# Optional contextmax_retries: 2,# Retry attempts (default: 2)max_steps: 5# Max processing steps (default: 5))putsresult.text# Generated text response

Telemetry Configuration

The gem supports OpenTelemetry integration for monitoring and observability. You can configure telemetry settings to control what data is recorded and add metadata for better tracing:

Telemetry Options:

  • enabled: Enable/disable telemetry (default: true)
  • record_inputs: Record input messages (default: false, disable for sensitive data)
  • record_outputs: Record output responses (default: false, disable for sensitive data)
  • function_id: Identifier for grouping telemetry data by function
  • metadata: Additional metadata for OpenTelemetry traces (agent identification, service info, etc.)
# Create telemetry settingstelemetry_settings=Ai::TelemetrySettings.new(enabled: true,record_inputs: false,# Disable for sensitive datarecord_outputs: true,# Enable for monitoringfunction_id: 'user-chat-session',metadata: {'agent.name'=>'customer-support','service.name'=>'mastra','service.namespace'=>'customer-service','cx.application.name'=>'ai-tracing','cx.subsystem.name'=>'mastra-agents'})# Use with text generationresult=agent.generate_text(messages: messages,telemetry: telemetry_settings)# Use with structured outputresult=agent.generate_object(messages: messages,output_class: Output,telemetry: telemetry_settings)

Workflows

Mastra "workflows" let you orchestrate multiple agents to solve a task.
The generator creates a lightweight Ruby wrapper that exposes typed Input and Output structs and a convenience .call method.

⚠️ there is no auto-conversion between snake case to pascal case (my_var → myVar) or back.

1. Generate a Workflow Client

# Generate a specific workflow
bin/rails generate ai:workflow --name="testWorkflow"# Generate all workflows present in Mastra
bin/rails generate ai:workflow --all

The generator will create files in app/generated/ai/workflows/.

2. Use the Workflow

input=Ai::Workflows::TestWorkflow::Input.new(first_number: 2.0,second_number: 3.0)# Run the workflowresult=Ai::Workflows::TestWorkflow.call(input)putsresult.sumOfNumbers# => 5.0

Example generated wrapper:

moduleAimoduleWorkflowsclassTestWorkflowextendT::SigclassInput < T::Structconst:first_number,Floatconst:second_number,FloatendclassOutput < T::Structconst:sumOfNumbers,Floatendsig{params(input: Input).returns(Output)}defself.call(input:)response=Ai.client.run_workflow('testWorkflow',input:)TypeCoerce[Output].from(response)rescueTypeCoerce::CoercionError,ArgumentError=>eraiseAi::Error,"Workflow 'testWorkflow' output could not be coerced: #{e.message}"endendendend

Generator Options

Both ai:agent and ai:workflow generators accept the same set of command-line flags:

  • --endpoint URL – Mastra API endpoint URL (default: value from MASTRA_LOCATION environment variable).
  • --all – Generate all agents/workflows found in Mastra.
  • --name NAME – Name of the agent/workflow to generate (required unless --all is provided).
  • --force – Override existing files if they already exist.
  • --output PATH – Output directory for generated files.
    • Agents default: app/generated/ai/agents
    • Workflows default: app/generated/ai/workflows

Generating your agents/workflows

rails generate ai:agent AGENT_NAME [options]rails generate ai:workflow WORKFLOW_NAME [options]

Basic Examples

The same applies for workflows.

# Generate a specific agent
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111
# Generate all agents from Mastra
bin/rails generate ai:agent --all --endpoint http://localhost:4111

Advanced Examples

# Generate with custom output directory
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --output lib/custom/agents
# Force overwrite existing files
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --force
# Generate all agents with custom settings
bin/rails generate ai:agent --all --endpoint http://localhost:4111 --output app/ai/agents --force

About

Ruby AI client to interact with Mastra agents

Resources

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

AI

A Ruby gem for integrating AI agents from Mastra into your Rails application. This gem provides a Rails generator to create and manage AI agents seamlessly within your Ruby applications.

Table of Contents

Overview

This gem provides a bridge between Mastra AI agents and your Rails application. It automatically generates client code for your agents and provides a consistent interface for calling them from your services.

Step-by-Step Guide

1. Create an Agent in Mastra

Before you can use an agent in your Ruby application, you need to create it in Mastra first:

  1. Create a new agent with your desired configuration
  2. Note the agent name (this will be used in the next step)
  3. Ensure the Mastra service is running and accessible

2. Generate the Agent Client

Once your agent is created in Mastra, generate the corresponding Ruby agent using the Rails generator:

# Generate all agents from Mastra
bin/rails generate ai:agent --all

This command will:

  • Fetch the agent configuration from Mastra
  • Generate the corresponding Ruby client file in app/generated/ai/agents/

3. Use the Agent in Your Rails Application

After generating the agent client, you can use it in your Rails application services:

Step 3.1: Define an Output Structure

Create a service that defines an output class using T::Struct:

classMyAgentServiceextendT::Sig# Define the expected output structureclassOutput < T::Structconst:result,Stringconst:confidence,Floatconst:metadata,T::Hash[String,T.untyped],default: {}endsig{params(input: String).returns(Output)}defself.call(input)# Your service logic heremessages=[Ai.user_message(input)]# Initialize the agent (this would typically be done once and reused)agent=Ai::Agent.new(agent_name: 'my_custom_agent',client: Ai::Client.new)# Generate structured outputresult=agent.generate_object(messages: messages,output_class: Output)endend

Step 3.2: Create Appropriate Messages

Structure your messages according to your agent's expected format:

messages=[Ai.system_message("You are a helpful assistant that..."),Ai.user_message("User's question or request")]

Sending Images:

For vision-capable agents, you can include images in your messages:

# Read image from fileimage_data=File.binread('path/to/image.png')# Create a message with text and imagemessage=Ai.user_message_with_image("What objects are in this image?",image_data,"image/png")messages=[message]

For multiple images in one message, use manual construction:

image1=File.binread('photo1.jpg')image2=File.binread('photo2.png')message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images:"),Ai::ImagePart.new(image_data: image1,media_type: "image/jpeg"),Ai::ImagePart.new(image_data: image2,media_type: "image/png")])

Sending documents (e.g. PDFs):

Providers that support file inputs can read documents directly — for PDFs the model sees both the embedded text layer and the rendered pages:

pdf_data=File.binread('path/to/invoice.pdf')message=Ai.user_message_with_file("Extract the invoice fields from this document",pdf_data,"application/pdf",filename: "invoice.pdf")messages=[message]

For custom combinations, Ai::FilePart composes with the other parts the same way Ai::ImagePart does:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these documents:"),Ai::FilePart.new(file_data: pdf1,media_type: "application/pdf",filename: "a.pdf"),Ai::FilePart.new(file_data: pdf2,media_type: "application/pdf",filename: "b.pdf")])

Using Image URLs:

Instead of sending image data, you can send a URL for the agent to fetch the image:

# Create a message with text and image URLmessage=Ai.user_message_with_image_url("What objects are in this image?","https://example.com/photo.jpg","image/jpeg")messages=[message]

For multiple image URLs or mixing URLs with text:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images from the web:"),Ai::ImagePart.new(image_url: "https://example.com/image1.jpg",media_type: "image/jpeg"),Ai::ImagePart.new(image_url: "https://example.com/image2.png",media_type: "image/png")])

Step 3.3: Call the Agent

# Use the service in your applicationresult=MyAgentService.call("What is the weather like today?")putsresult.result# => Agent's responseputsresult.confidence# => Confidence scoreputsresult.metadata# => Additional metadata

Advanced Usage

The generate_object method supports additional options for fine-tuning:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_object(messages: messages,output_class: Output,request_context: {user_id: 123,session: 'abc'},# Optional contextmax_retries: 3,# Retry attempts (default: 2)max_steps: 10# Max processing steps (default: 5))# Access the structured outputoutput=result.objectputsoutput.result

For simple text generation without structured output:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_text(messages: messages,request_context: {},# Optional contextmax_retries: 2,# Retry attempts (default: 2)max_steps: 5# Max processing steps (default: 5))putsresult.text# Generated text response

Telemetry Configuration

The gem supports OpenTelemetry integration for monitoring and observability. You can configure telemetry settings to control what data is recorded and add metadata for better tracing:

Telemetry Options:

  • enabled: Enable/disable telemetry (default: true)
  • record_inputs: Record input messages (default: false, disable for sensitive data)
  • record_outputs: Record output responses (default: false, disable for sensitive data)
  • function_id: Identifier for grouping telemetry data by function
  • metadata: Additional metadata for OpenTelemetry traces (agent identification, service info, etc.)
# Create telemetry settingstelemetry_settings=Ai::TelemetrySettings.new(enabled: true,record_inputs: false,# Disable for sensitive datarecord_outputs: true,# Enable for monitoringfunction_id: 'user-chat-session',metadata: {'agent.name'=>'customer-support','service.name'=>'mastra','service.namespace'=>'customer-service','cx.application.name'=>'ai-tracing','cx.subsystem.name'=>'mastra-agents'})# Use with text generationresult=agent.generate_text(messages: messages,telemetry: telemetry_settings)# Use with structured outputresult=agent.generate_object(messages: messages,output_class: Output,telemetry: telemetry_settings)

Workflows

Mastra "workflows" let you orchestrate multiple agents to solve a task.
The generator creates a lightweight Ruby wrapper that exposes typed Input and Output structs and a convenience .call method.

⚠️ there is no auto-conversion between snake case to pascal case (my_var → myVar) or back.

1. Generate a Workflow Client

# Generate a specific workflow
bin/rails generate ai:workflow --name="testWorkflow"# Generate all workflows present in Mastra
bin/rails generate ai:workflow --all

The generator will create files in app/generated/ai/workflows/.

2. Use the Workflow

input=Ai::Workflows::TestWorkflow::Input.new(first_number: 2.0,second_number: 3.0)# Run the workflowresult=Ai::Workflows::TestWorkflow.call(input)putsresult.sumOfNumbers# => 5.0

Example generated wrapper:

moduleAimoduleWorkflowsclassTestWorkflowextendT::SigclassInput < T::Structconst:first_number,Floatconst:second_number,FloatendclassOutput < T::Structconst:sumOfNumbers,Floatendsig{params(input: Input).returns(Output)}defself.call(input:)response=Ai.client.run_workflow('testWorkflow',input:)TypeCoerce[Output].from(response)rescueTypeCoerce::CoercionError,ArgumentError=>eraiseAi::Error,"Workflow 'testWorkflow' output could not be coerced: #{e.message}"endendendend

Generator Options

Both ai:agent and ai:workflow generators accept the same set of command-line flags:

  • --endpoint URL – Mastra API endpoint URL (default: value from MASTRA_LOCATION environment variable).
  • --all – Generate all agents/workflows found in Mastra.
  • --name NAME – Name of the agent/workflow to generate (required unless --all is provided).
  • --force – Override existing files if they already exist.
  • --output PATH – Output directory for generated files.
    • Agents default: app/generated/ai/agents
    • Workflows default: app/generated/ai/workflows

Generating your agents/workflows

rails generate ai:agent AGENT_NAME [options]rails generate ai:workflow WORKFLOW_NAME [options]

Basic Examples

The same applies for workflows.

# Generate a specific agent
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111
# Generate all agents from Mastra
bin/rails generate ai:agent --all --endpoint http://localhost:4111

Advanced Examples

# Generate with custom output directory
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --output lib/custom/agents
# Force overwrite existing files
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --force
# Generate all agents with custom settings
bin/rails generate ai:agent --all --endpoint http://localhost:4111 --output app/ai/agents --force

About

Ruby AI client to interact with Mastra agents

Resources

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

AI

A Ruby gem for integrating AI agents from Mastra into your Rails application. This gem provides a Rails generator to create and manage AI agents seamlessly within your Ruby applications.

Table of Contents

Overview

This gem provides a bridge between Mastra AI agents and your Rails application. It automatically generates client code for your agents and provides a consistent interface for calling them from your services.

Step-by-Step Guide

1. Create an Agent in Mastra

Before you can use an agent in your Ruby application, you need to create it in Mastra first:

  1. Create a new agent with your desired configuration
  2. Note the agent name (this will be used in the next step)
  3. Ensure the Mastra service is running and accessible

2. Generate the Agent Client

Once your agent is created in Mastra, generate the corresponding Ruby agent using the Rails generator:

# Generate all agents from Mastra
bin/rails generate ai:agent --all

This command will:

  • Fetch the agent configuration from Mastra
  • Generate the corresponding Ruby client file in app/generated/ai/agents/

3. Use the Agent in Your Rails Application

After generating the agent client, you can use it in your Rails application services:

Step 3.1: Define an Output Structure

Create a service that defines an output class using T::Struct:

classMyAgentServiceextendT::Sig# Define the expected output structureclassOutput < T::Structconst:result,Stringconst:confidence,Floatconst:metadata,T::Hash[String,T.untyped],default: {}endsig{params(input: String).returns(Output)}defself.call(input)# Your service logic heremessages=[Ai.user_message(input)]# Initialize the agent (this would typically be done once and reused)agent=Ai::Agent.new(agent_name: 'my_custom_agent',client: Ai::Client.new)# Generate structured outputresult=agent.generate_object(messages: messages,output_class: Output)endend

Step 3.2: Create Appropriate Messages

Structure your messages according to your agent's expected format:

messages=[Ai.system_message("You are a helpful assistant that..."),Ai.user_message("User's question or request")]

Sending Images:

For vision-capable agents, you can include images in your messages:

# Read image from fileimage_data=File.binread('path/to/image.png')# Create a message with text and imagemessage=Ai.user_message_with_image("What objects are in this image?",image_data,"image/png")messages=[message]

For multiple images in one message, use manual construction:

image1=File.binread('photo1.jpg')image2=File.binread('photo2.png')message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images:"),Ai::ImagePart.new(image_data: image1,media_type: "image/jpeg"),Ai::ImagePart.new(image_data: image2,media_type: "image/png")])

Sending documents (e.g. PDFs):

Providers that support file inputs can read documents directly — for PDFs the model sees both the embedded text layer and the rendered pages:

pdf_data=File.binread('path/to/invoice.pdf')message=Ai.user_message_with_file("Extract the invoice fields from this document",pdf_data,"application/pdf",filename: "invoice.pdf")messages=[message]

For custom combinations, Ai::FilePart composes with the other parts the same way Ai::ImagePart does:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these documents:"),Ai::FilePart.new(file_data: pdf1,media_type: "application/pdf",filename: "a.pdf"),Ai::FilePart.new(file_data: pdf2,media_type: "application/pdf",filename: "b.pdf")])

Using Image URLs:

Instead of sending image data, you can send a URL for the agent to fetch the image:

# Create a message with text and image URLmessage=Ai.user_message_with_image_url("What objects are in this image?","https://example.com/photo.jpg","image/jpeg")messages=[message]

For multiple image URLs or mixing URLs with text:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images from the web:"),Ai::ImagePart.new(image_url: "https://example.com/image1.jpg",media_type: "image/jpeg"),Ai::ImagePart.new(image_url: "https://example.com/image2.png",media_type: "image/png")])

Step 3.3: Call the Agent

# Use the service in your applicationresult=MyAgentService.call("What is the weather like today?")putsresult.result# => Agent's responseputsresult.confidence# => Confidence scoreputsresult.metadata# => Additional metadata

Advanced Usage

The generate_object method supports additional options for fine-tuning:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_object(messages: messages,output_class: Output,request_context: {user_id: 123,session: 'abc'},# Optional contextmax_retries: 3,# Retry attempts (default: 2)max_steps: 10# Max processing steps (default: 5))# Access the structured outputoutput=result.objectputsoutput.result

For simple text generation without structured output:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_text(messages: messages,request_context: {},# Optional contextmax_retries: 2,# Retry attempts (default: 2)max_steps: 5# Max processing steps (default: 5))putsresult.text# Generated text response

Telemetry Configuration

The gem supports OpenTelemetry integration for monitoring and observability. You can configure telemetry settings to control what data is recorded and add metadata for better tracing:

Telemetry Options:

  • enabled: Enable/disable telemetry (default: true)
  • record_inputs: Record input messages (default: false, disable for sensitive data)
  • record_outputs: Record output responses (default: false, disable for sensitive data)
  • function_id: Identifier for grouping telemetry data by function
  • metadata: Additional metadata for OpenTelemetry traces (agent identification, service info, etc.)
# Create telemetry settingstelemetry_settings=Ai::TelemetrySettings.new(enabled: true,record_inputs: false,# Disable for sensitive datarecord_outputs: true,# Enable for monitoringfunction_id: 'user-chat-session',metadata: {'agent.name'=>'customer-support','service.name'=>'mastra','service.namespace'=>'customer-service','cx.application.name'=>'ai-tracing','cx.subsystem.name'=>'mastra-agents'})# Use with text generationresult=agent.generate_text(messages: messages,telemetry: telemetry_settings)# Use with structured outputresult=agent.generate_object(messages: messages,output_class: Output,telemetry: telemetry_settings)

Workflows

Mastra "workflows" let you orchestrate multiple agents to solve a task.
The generator creates a lightweight Ruby wrapper that exposes typed Input and Output structs and a convenience .call method.

⚠️ there is no auto-conversion between snake case to pascal case (my_var → myVar) or back.

1. Generate a Workflow Client

# Generate a specific workflow
bin/rails generate ai:workflow --name="testWorkflow"# Generate all workflows present in Mastra
bin/rails generate ai:workflow --all

The generator will create files in app/generated/ai/workflows/.

2. Use the Workflow

input=Ai::Workflows::TestWorkflow::Input.new(first_number: 2.0,second_number: 3.0)# Run the workflowresult=Ai::Workflows::TestWorkflow.call(input)putsresult.sumOfNumbers# => 5.0

Example generated wrapper:

moduleAimoduleWorkflowsclassTestWorkflowextendT::SigclassInput < T::Structconst:first_number,Floatconst:second_number,FloatendclassOutput < T::Structconst:sumOfNumbers,Floatendsig{params(input: Input).returns(Output)}defself.call(input:)response=Ai.client.run_workflow('testWorkflow',input:)TypeCoerce[Output].from(response)rescueTypeCoerce::CoercionError,ArgumentError=>eraiseAi::Error,"Workflow 'testWorkflow' output could not be coerced: #{e.message}"endendendend

Generator Options

Both ai:agent and ai:workflow generators accept the same set of command-line flags:

  • --endpoint URL – Mastra API endpoint URL (default: value from MASTRA_LOCATION environment variable).
  • --all – Generate all agents/workflows found in Mastra.
  • --name NAME – Name of the agent/workflow to generate (required unless --all is provided).
  • --force – Override existing files if they already exist.
  • --output PATH – Output directory for generated files.
    • Agents default: app/generated/ai/agents
    • Workflows default: app/generated/ai/workflows

Generating your agents/workflows

rails generate ai:agent AGENT_NAME [options]rails generate ai:workflow WORKFLOW_NAME [options]

Basic Examples

The same applies for workflows.

# Generate a specific agent
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111
# Generate all agents from Mastra
bin/rails generate ai:agent --all --endpoint http://localhost:4111

Advanced Examples

# Generate with custom output directory
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --output lib/custom/agents
# Force overwrite existing files
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --force
# Generate all agents with custom settings
bin/rails generate ai:agent --all --endpoint http://localhost:4111 --output app/ai/agents --force

About

Ruby AI client to interact with Mastra agents

Resources

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

AI

A Ruby gem for integrating AI agents from Mastra into your Rails application. This gem provides a Rails generator to create and manage AI agents seamlessly within your Ruby applications.

Table of Contents

Overview

This gem provides a bridge between Mastra AI agents and your Rails application. It automatically generates client code for your agents and provides a consistent interface for calling them from your services.

Step-by-Step Guide

1. Create an Agent in Mastra

Before you can use an agent in your Ruby application, you need to create it in Mastra first:

  1. Create a new agent with your desired configuration
  2. Note the agent name (this will be used in the next step)
  3. Ensure the Mastra service is running and accessible

2. Generate the Agent Client

Once your agent is created in Mastra, generate the corresponding Ruby agent using the Rails generator:

# Generate all agents from Mastra
bin/rails generate ai:agent --all

This command will:

  • Fetch the agent configuration from Mastra
  • Generate the corresponding Ruby client file in app/generated/ai/agents/

3. Use the Agent in Your Rails Application

After generating the agent client, you can use it in your Rails application services:

Step 3.1: Define an Output Structure

Create a service that defines an output class using T::Struct:

classMyAgentServiceextendT::Sig# Define the expected output structureclassOutput < T::Structconst:result,Stringconst:confidence,Floatconst:metadata,T::Hash[String,T.untyped],default: {}endsig{params(input: String).returns(Output)}defself.call(input)# Your service logic heremessages=[Ai.user_message(input)]# Initialize the agent (this would typically be done once and reused)agent=Ai::Agent.new(agent_name: 'my_custom_agent',client: Ai::Client.new)# Generate structured outputresult=agent.generate_object(messages: messages,output_class: Output)endend

Step 3.2: Create Appropriate Messages

Structure your messages according to your agent's expected format:

messages=[Ai.system_message("You are a helpful assistant that..."),Ai.user_message("User's question or request")]

Sending Images:

For vision-capable agents, you can include images in your messages:

# Read image from fileimage_data=File.binread('path/to/image.png')# Create a message with text and imagemessage=Ai.user_message_with_image("What objects are in this image?",image_data,"image/png")messages=[message]

For multiple images in one message, use manual construction:

image1=File.binread('photo1.jpg')image2=File.binread('photo2.png')message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images:"),Ai::ImagePart.new(image_data: image1,media_type: "image/jpeg"),Ai::ImagePart.new(image_data: image2,media_type: "image/png")])

Sending documents (e.g. PDFs):

Providers that support file inputs can read documents directly — for PDFs the model sees both the embedded text layer and the rendered pages:

pdf_data=File.binread('path/to/invoice.pdf')message=Ai.user_message_with_file("Extract the invoice fields from this document",pdf_data,"application/pdf",filename: "invoice.pdf")messages=[message]

For custom combinations, Ai::FilePart composes with the other parts the same way Ai::ImagePart does:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these documents:"),Ai::FilePart.new(file_data: pdf1,media_type: "application/pdf",filename: "a.pdf"),Ai::FilePart.new(file_data: pdf2,media_type: "application/pdf",filename: "b.pdf")])

Using Image URLs:

Instead of sending image data, you can send a URL for the agent to fetch the image:

# Create a message with text and image URLmessage=Ai.user_message_with_image_url("What objects are in this image?","https://example.com/photo.jpg","image/jpeg")messages=[message]

For multiple image URLs or mixing URLs with text:

message=Ai::Message.new(role: Ai::MessageRole::User,content: [Ai::TextPart.new(text: "Compare these images from the web:"),Ai::ImagePart.new(image_url: "https://example.com/image1.jpg",media_type: "image/jpeg"),Ai::ImagePart.new(image_url: "https://example.com/image2.png",media_type: "image/png")])

Step 3.3: Call the Agent

# Use the service in your applicationresult=MyAgentService.call("What is the weather like today?")putsresult.result# => Agent's responseputsresult.confidence# => Confidence scoreputsresult.metadata# => Additional metadata

Advanced Usage

The generate_object method supports additional options for fine-tuning:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_object(messages: messages,output_class: Output,request_context: {user_id: 123,session: 'abc'},# Optional contextmax_retries: 3,# Retry attempts (default: 2)max_steps: 10# Max processing steps (default: 5))# Access the structured outputoutput=result.objectputsoutput.result

For simple text generation without structured output:

agent=Ai::Agent.new(agent_name: 'my_agent',client: Ai::Client.new)result=agent.generate_text(messages: messages,request_context: {},# Optional contextmax_retries: 2,# Retry attempts (default: 2)max_steps: 5# Max processing steps (default: 5))putsresult.text# Generated text response

Telemetry Configuration

The gem supports OpenTelemetry integration for monitoring and observability. You can configure telemetry settings to control what data is recorded and add metadata for better tracing:

Telemetry Options:

  • enabled: Enable/disable telemetry (default: true)
  • record_inputs: Record input messages (default: false, disable for sensitive data)
  • record_outputs: Record output responses (default: false, disable for sensitive data)
  • function_id: Identifier for grouping telemetry data by function
  • metadata: Additional metadata for OpenTelemetry traces (agent identification, service info, etc.)
# Create telemetry settingstelemetry_settings=Ai::TelemetrySettings.new(enabled: true,record_inputs: false,# Disable for sensitive datarecord_outputs: true,# Enable for monitoringfunction_id: 'user-chat-session',metadata: {'agent.name'=>'customer-support','service.name'=>'mastra','service.namespace'=>'customer-service','cx.application.name'=>'ai-tracing','cx.subsystem.name'=>'mastra-agents'})# Use with text generationresult=agent.generate_text(messages: messages,telemetry: telemetry_settings)# Use with structured outputresult=agent.generate_object(messages: messages,output_class: Output,telemetry: telemetry_settings)

Workflows

Mastra "workflows" let you orchestrate multiple agents to solve a task.
The generator creates a lightweight Ruby wrapper that exposes typed Input and Output structs and a convenience .call method.

⚠️ there is no auto-conversion between snake case to pascal case (my_var → myVar) or back.

1. Generate a Workflow Client

# Generate a specific workflow
bin/rails generate ai:workflow --name="testWorkflow"# Generate all workflows present in Mastra
bin/rails generate ai:workflow --all

The generator will create files in app/generated/ai/workflows/.

2. Use the Workflow

input=Ai::Workflows::TestWorkflow::Input.new(first_number: 2.0,second_number: 3.0)# Run the workflowresult=Ai::Workflows::TestWorkflow.call(input)putsresult.sumOfNumbers# => 5.0

Example generated wrapper:

moduleAimoduleWorkflowsclassTestWorkflowextendT::SigclassInput < T::Structconst:first_number,Floatconst:second_number,FloatendclassOutput < T::Structconst:sumOfNumbers,Floatendsig{params(input: Input).returns(Output)}defself.call(input:)response=Ai.client.run_workflow('testWorkflow',input:)TypeCoerce[Output].from(response)rescueTypeCoerce::CoercionError,ArgumentError=>eraiseAi::Error,"Workflow 'testWorkflow' output could not be coerced: #{e.message}"endendendend

Generator Options

Both ai:agent and ai:workflow generators accept the same set of command-line flags:

  • --endpoint URL – Mastra API endpoint URL (default: value from MASTRA_LOCATION environment variable).
  • --all – Generate all agents/workflows found in Mastra.
  • --name NAME – Name of the agent/workflow to generate (required unless --all is provided).
  • --force – Override existing files if they already exist.
  • --output PATH – Output directory for generated files.
    • Agents default: app/generated/ai/agents
    • Workflows default: app/generated/ai/workflows

Generating your agents/workflows

rails generate ai:agent AGENT_NAME [options]rails generate ai:workflow WORKFLOW_NAME [options]

Basic Examples

The same applies for workflows.

# Generate a specific agent
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111
# Generate all agents from Mastra
bin/rails generate ai:agent --all --endpoint http://localhost:4111

Advanced Examples

# Generate with custom output directory
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --output lib/custom/agents
# Force overwrite existing files
bin/rails generate ai:agent my_agent --endpoint http://localhost:4111 --force
# Generate all agents with custom settings
bin/rails generate ai:agent --all --endpoint http://localhost:4111 --output app/ai/agents --force

About

Ruby AI client to interact with Mastra agents

Resources

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages