mugib_sdk 1.0.22 copy "mugib_sdk: ^1.0.22" to clipboard
mugib_sdk: ^1.0.22 copied to clipboard

Official Flutter SDK for Mugib chat sessions, voice agents, and session payload with one apiKey.

mugib_sdk #

Official unified Flutter SDK for Mugib end-user chat & voice apps.

One project API key — connect your app to a Mugib Agent:

  • Chat — sessions, messages (JSON + SSE), payload per session
  • Voice — real-time Mugib Voice AI
  • Widget UI (read-only) — bot name, welcome message, quick replies, proactive triggers

Your app talks to the Agent — it does not configure it.
KB, MCP data sources, function-calling tools, prompts, and confirmation rules are set in Portal and handled by the backend + AI during each message.
payload only passes user context for one session (name, balance, plan, …).


SDK scope #

Layer What changes SDK access
Session Messages, payload, CSAT, conversions mugib.chat.* ✅ main
Voice Call + transcripts + session context mugib.voice.* ✅ main
Widget UI Read branding/triggers getWidgetConfig(), getWidgetTriggers() ✅ optional
Tenant KB Adds/edits KB for whole project MugibKbService(mugib.api) ⚠️ advanced only
Tenant settings Bot prompt, personality ❌ Portal/Admin only

What you need #

Item Where
Project API key Project → Settings → API Key
Voice agent id (voice only) Project → Voice Agents → numeric id
API base URL https://api.mugib.com (default)

Install #

dependencies:
  mugib_sdk: ^1.0.21
flutter pub get

Requirements: Flutter 3.24+ / Dart 3.5+ · iOS & Android (voice needs microphone permissions).


Quick start — enough for most apps #

import 'package:mugib_sdk/mugib_sdk.dart';

final mugib = MugibClient(apiKey: 'YOUR_PROJECT_API_KEY');

// 1. Open session
final session = await mugib.chat.createSession();

// 2. Send messages — backend handles KB, MCP, tools, and AI replies
final reply = await session.send(
  'What plan fits me?',
  payload: {'name': 'Ahmed', 'plan': 'trial'},
);
print(reply.reply);

// If the bot asks "Confirm this action?" — just send yes/no:
await session.send('yes');

That is the full integration for ~90% of apps. No MCP setup, no tool config, no confirmation APIs in your code.

Chat + voice (optional) #

await MugibSdk.initialize(); // once at app startup (required for voice)

// Streaming (SSE)
await for (final event in session.sendStream('Explain Pro plan')) {
  if (event is MugibStreamText) stdout.write(event.text);
}

// Voice call — same session context; verbal yes/no for tool approval works automatically
final call = mugib.voice.client(34, preferSpeaker: false); // earpiece default — less echo
await call.start(options: MugibVoiceCallOptions(
  chatSessionId: session.id,
  userContext: {'name': 'Ahmed'},
));
call.transcriptLines.listen((lines) {
  // Ready-to-render list — partial fragments merged by the SDK
  for (final t in lines) print('${t.role}: ${t.text}');
});
await call.end();

Chat API #

MugibClient.chat #

Method REST endpoint Description
createSession({pageUrl}) POST /api/v1/sessions New session (chat_…)
listSessions() GET /api/v1/sessions Active sessions
session(id) Bind existing session id

MugibChatSession #

Method REST endpoint Description
send(message, {payload}) POST …/messages Blocking JSON reply
sendStream(message, {payload}) POST …/messages?stream=true SSE token stream
sendStreamText(…) same Convenience: full string
getHistory() GET …/sessions/{id} Message history
reset() DELETE …/sessions/{id} Clear session
trackConversion({goalName, …}) POST …/conversions Conversion event
submitCsat({rating, comment}) POST /api/v1/csat/{id} 1–5 star rating

Payload #

Pass dynamic user context on every message (merged server-side):

await session.send('Check my balance', payload: {
  'name': 'أحمد',
  'account_id': 'ACC-9921',
  'balance': '45 IQD',
});

The same payload is reused when you pass chatSessionId to a voice call.

Streaming metadata #

The final SSE event may be MugibStreamMetadata with KB sources:

await for (final event in session.sendStream('…')) {
  switch (event) {
    case MugibStreamText(:final text):
      print(text);
    case MugibStreamMetadata(:final sources):
      print('Sources: ${sources.map((s) => s.title)}');
  }
}

Voice API #

Voice behaviour — see voice section in docs/flutter-sdk.md for permissions, errors, and metrics.

// List agents
final agents = await mugib.voice.listAgents();

// Create call client — preferSpeaker defaults to false (earpiece / cleaner AEC)
final call = mugib.voice.client(
  agents.first.id,
  preferSpeaker: false, // set true only if you need loudspeaker output
);
await call.start(); // or MugibVoiceCallOptions for payload / chatSessionId

// Analytics
final stats = await mugib.voice.analytics(34, days: 7);

Echo guard & barge-in (1.0.21+) #

On phones, speaker playback can feed back into the mic and trigger false interruptions. The SDK mitigates this in three layers:

Layer What it does
Audio routing preferSpeaker: false (default) routes agent audio through earpiece/receiver on iOS and Android — much cleaner than forced loudspeaker
Client echo guard While agent PCM is playing, mic uplink is suppressed unless input level exceeds a barge-in threshold — real user speech still gets through
Server echo gate Mugib backend applies matching filters (voice.echo_guard_ms, voice.barge_in_threshold in Admin settings)

The SDK sends {type: "client_state", playback_active, input_level} to the server every ~150 ms so both sides stay in sync.

// Default — recommended for mobile
final call = mugib.voice.client(agentId); // preferSpeaker: false

// Loudspeaker (e.g. demo kiosk) — higher echo risk; use headphones if possible
final call = mugib.voice.client(agentId, preferSpeaker: true);

allowInterruption comes from the voice agent token (/token). When barge-in is disabled in Portal, uplink pauses entirely while agent audio plays (half-duplex).

Live call streams #

Bind these to your UI — the SDK handles mic, playback, reconnect, and transcript merging for you:

Stream Type Use
state MugibCallState idle / connecting / connected / listening / speaking / ended / error
transcriptLines List<MugibTranscript> Ready-to-render transcript (partial fragments merged)
inputLevel double (0.0–1.0) Smoothed mic level — drive a level meter so users see their mic is captured
durationTicks Duration Elapsed call time (~1/sec)
metrics MugibCallMetrics Time-to-first-audio + response latency
errorEvents MugibVoiceError Structured errors (branch on .code)
call.state.listen((s) => setState(() => _state = s));
call.transcriptLines.listen((lines) => setState(() => _lines = lines));
call.inputLevel.listen((level) => setState(() => _micLevel = level)); // 0..1 meter
call.errorEvents.listen((e) => showError(_friendly(e.code)));

call.toggleMute(); // returns the new muted state
await call.end();

A full voice-call screen — call state pill + timer, animated mic orb, input level meter, live transcript bubbles, mute, and friendly error UI — is in example/lib/main.dart.


Widget UI (read-only, optional) #

Load branding for a custom chat screen — does not modify tenant settings:

final config = await mugib.getWidgetConfig();
print(config.botName);
print(config.welcomeMessage);
print(config.quickReplies);

Proactive triggers (optional) #

Not from KB. Triggers are rules the project owner adds in Portal → Triggers (same as projects/{id}/triggers): e.g. show a message after 30 seconds on /pricing.

final triggers = await mugib.getWidgetTriggers();
// [] when none configured — not an error
for (final t in triggers) {
  print('${t.triggerType}: ${t.message}');
}
Item Detail
Configured in Portal → Project → Triggers
REST GET /api/v1/widget/triggers
When empty { "triggers": [] }
Required? No — chat & voice work without calling this

Most Flutter apps can skip getWidgetTriggers() entirely.


Advanced chat UI (optional) #

Use only when you build a full custom chat screen like the web widget. Most apps can ignore this.

What the backend does (not your app) #

Feature Who configures Who runs it SDK needed?
MCP data search (KB, SQL, REST…) Portal Backend — automatic on every message No
Function-calling tools (email, webhook…) Portal AI decides when to call; backend executes No
Tool approval Portal (requires_confirmation flag) Backend asks user; send("yes") or voice "yes" works No*
Human handoff Portal (live agents) Agent takes over in Portal; bot stops replying poll() to show agent replies

* confirmTool() is an optional UI helper for Confirm/Cancel buttons — same as the web widget. Text chat: send("yes") is enough. Voice: say "yes" / "no" — handled automatically.

Human handoff — show agent messages #

When a live agent takes over, bot replies stop. Poll for human-agent messages:

final poll = await session.poll(agentAfter: lastAgentCount);
if (poll.isHuman) {
  for (final msg in poll.agentMessages) {
    print('${msg.name}: ${msg.content}');
  }
}
Method REST endpoint Description
poll({agentAfter}) GET …/poll Human-agent messages during handoff

Tool approval buttons (optional UI) #

When a Portal tool requires confirmation, the bot asks in chat. Default: user replies send("yes") or send("no").

For Confirm/Cancel buttons instead of typed replies:

final pending = await session.pendingConfirmations();
for (final p in pending) {
  // show p.summary in UI
  await session.confirmTool(p.confirmationId, confirm: true);
}
Method REST endpoint Description
pendingConfirmations() GET …/pending-confirmations Tools awaiting user approval
confirmTool(id, {confirm}) POST …/confirmations/{id} Approve / decline via button

Advanced (tenant-wide — use with care) #

KB CRUD via API key changes the whole project KB, not one session. Prefer Portal for KB management; use only for automated sync:

final kb = MugibKbService(mugib.api);
await kb.list(search: 'pricing'); // read
// await kb.add(...) // writes tenant KB — advanced integrations only

Platform permissions (voice) #

iOS — Info.plist #

<key>NSMicrophoneUsageDescription</key>
<string>We need the microphone for voice conversations with our support agent.</string>

For cleaner echo cancellation, keep the default preferSpeaker: false (receiver). Only opt into loudspeaker when your UX requires it.

Android — AndroidManifest.xml #

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />

minSdkVersion 23 or higher.


Error handling #

try {
  await session.send('Hello');
} on MugibException catch (e) {
  switch (e.code) {
    case MugibErrorCode.quotaExceeded:
      // upgrade plan
    case MugibErrorCode.rateLimited:
      // slow down
    default:
      print(e.message);
  }
}

Voice errors use MugibVoiceException / MugibVoiceErrorCode.


Example app #

Runnable demo with a chat screen and a full voice-call screen (call controls, live transcript, mic level meter, friendly error UI):

cd sdk/flutter/mugib_sdk/example
flutter pub get
flutter run \
  --dart-define=MUGIB_API_KEY=your_key \
  --dart-define=MUGIB_AGENT_ID=34

Maintainers #

cd sdk/flutter/mugib_sdk
make help
make check
make update   # publish to pub.dev

See PUBLISHING.md.



License #

MIT — see LICENSE.

1
likes
150
points
1.1k
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Official Flutter SDK for Mugib chat sessions, voice agents, and session payload with one apiKey.

Homepage
Repository (GitHub)
View/report issues

Topics

#ai #chatbot #voice #sdk #mugib-voice

License

MIT (license)

Dependencies

audio_session, flutter, flutter_pcm_sound, http, record, web_socket_channel

More

Packages that depend on mugib_sdk