Eureka AI
Agent Service Documentation
Processing
What is the Agent service?
Agent is a sub-service of Eureka AI that automates monitoring and generates recommendations based on predefined conditions. It consists of multiple Monitors that trigger at specified intervals to analyze data and determine if a recommendation should be created.
If a recommendation is created, it can include:
- Context (used by the frontend View for rendering)
- Actions (various response mechanisms)
- Notifications (alerts sent to users)
Using Agent on the Platform
Where to find recommendations?
Once created, recommendations are available on the Recommendations page, where users can review and act on them.
Configuring Agents (Monitors)
Monitors are configurable within the Organization Settings, allowing customization of triggers, recurrence, and actions based on specific organizational needs.
Triggering Monitors
Monitors are executed automatically based on a scheduled task:
$schedule->command(DispatchActiveAgentCommand::class)->everyMinute();This command fetches all active monitors and dispatches them accordingly.
Execution Flow
- The system retrieves all active agents.
- Each agent runs in a Job that:
- Sets up the Tenancy Manager (See Tenancy Manager Documentation)
- Initializes the correct Monitor via
AgentFactory::make() - Executes the monitor logic using
$monitor->execute($subject)
Note: The Monitor receives data with an active Tenancy Manager, meaning data access is already scoped to the relevant Team or Organization.
Monitor
What is a monitor?
A Monitor is a component within the Agent service that runs at a specified recurrence interval to analyze data and determine if action is needed.
Create a new monitor
To create a new Monitor, define its settings, implement the monitoring logic, and configure the response.
Settings
Title: The name of the monitor.
Description: A brief explanation of the monitor’s purpose.
Recurrence: Defines how often the monitor runs (e.g., daily, weekly).
Subject: Determines whether the monitor applies to a Team or an Organization. This defines what type of model
$subjectwill be in themonitor()method:- If
SubjectEnum::TEAM, then$subjectis an instance of aTeam. - If
SubjectEnum::ORGANIZATION, then$subjectis an instance of anOrganization.
This helps determine at what level the monitor should apply its logic.
- If
View: The frontend component used to display the recommendation. This component must be placed in
resources/js/Components/Agent/Monitors/*, otherwise an error will occur during rendering.
Example Monitor Implementation
class FeedbackAnomalyMonitor extends AbstractMonitor
{
public function settings(): MonitorSettings
{
return new MonitorSettings(
title: 'Feedback Anomaly Detection',
description: new HtmlString('Detects sudden drops in feedback volume and alerts the admin.'),
recurrence: RecurrenceEnum::DAILY,
subject: SubjectEnum::ORGANIZATION,
view: new FeedbackAnomalyView(),
);
}
public function monitor(Model $subject, ?Carbon $lastExecution = null): MonitorResponse
{
$feedbackDrop = rand(0, 1); // Simulating anomaly detection
return new MonitorResponse(createRecommendation: (bool) $feedbackDrop)
->addContext('drop_percentage', 35)
->addContext('affected_surveys', [101, 202, 303])
->addAction(new ResolveAnomalyAction())
->addNotificationIfSuccess(
new NewMonitorNotification('A 35% drop in feedback volume detected!')
);
}
}You have to create a database migration to insert your new monitor.
Example Monitor Migration
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
public function up(): void
{
DB::table('agents')->insert([
'monitor_name' => 'admin.team_description',
'created_at' => now(),
'updated_at' => now(),
]);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
DB::table('agents')->where('monitor_name', '=', 'admin.team_description')?->delete();
}
};Actions
What is an Action?
An Action represents an operation that a user can perform on a recommendation.
Creating an Action
Actions extend AbstractAction and implement the Actionable interface.
Example Action Implementation
class ResolveAnomalyAction extends AbstractAction
{
protected function execute(Request $request, array $context): mixed
{
// Example: Retrieving the drop percentage from the context
$dropPercentage = $context['drop_percentage'] ?? null;
return redirect()->back()->with(
SuccessFlash::notify('Success', "Anomaly of $dropPercentage% resolved successfully!")
);
}
}Inside the action, it is possible to get and set the action, if needed.
$this->getAction()
$this->setAction()Action Execution Flow
- A user clicks the action button.
- The
handle()method is called with the current request and context. - The action executes the logic defined in the
execute()method. - Once executed, the action is marked as executed and cannot be triggered again.
Notifications
A notification in Agent is a Notify. See the full documentation at User Notifications.
Adding Notifications
Notifications can be added in two ways:
public function addNotificationIfSuccess(Notification $notification): selfThis method sends a notification only if a recommendation is created.
public function addNotification(Notification $notification): selfThis method sends a notification always, regardless of whether a recommendation is created or not.
Notification Recipients
Notifications are sent only to users who have access to the recommendation. Access is determined via capabilities.
Notification Broadcasting
Notifications are broadcasted in real-time. By default, you can use:
new NewMonitorNotification()This standard notification sends both an in-app notification and an email to the relevant users.
View
Create a new component
Frontend components for Agent are stored in resources/js/Components/Agent/Monitors/*.
Example JavaScript component
<script setup>
const props = defineProps({
actions: Object,
properties: Object,
});
const getAcceptAction = (survey) => getAction('survey.accept.', survey.name);
const accept = (survey) => {
const action = getAcceptAction(survey);
form.post(route('agent.action', [props.actions[0].agent_recommendation_id, action.key]), {
preserveState: false,
preserveScroll: true,
});
};
</script>
<template>
<div>
<p>Feedback volume dropped by {{ properties.drop_percentage }}%.</p>
<p>Affected surveys: {{ properties.affected_surveys.join(", ") }}</p>
<div v-for="survey in properties.affected_surveys" :key="survey">
<PrimaryButton @click="accept(survey)" class="h-8">
<font-awesome-icon icon="fa-regular fa-check" class="text-white h-3 w-3" />
Accept
</PrimaryButton>
</div>
</div>
</template>Test the agent locally
new MyAgent()->execute($subject);Note that $subject can be a team or an organization, depending on what you defined in your Monitor settings() method.