Marona Dart SDK

Run Agents through one managed API, with structured output, local tools, Hub capabilities, streaming, realtime and A2A collaboration.

Install

Version 2.0.0. Package registry.

Dart 3.10+. This is a server or command line example, not a Flutter Web example.

dart pub add 'marona:^2.0.0'

Set MARONA_API_KEY in your backend environment. Never commit it, log it, or embed a developer key in browser or mobile code. Use an exact accessible marona/* model alias from Marona Platform.

Agent quickstart

Save as example/agent_example.dart. Run without arguments for text, or with a real PNG/JPEG path for document extraction. Use stable application user IDs and a distinct session ID for each conversation.

import 'dart:convert';
import 'dart:io';
import 'package:marona/marona.dart';

Future<void> main(List<String> args) async {
  final marona = Marona(
    apiKey: Platform.environment['MARONA_API_KEY'],
    baseUrl:
        Platform.environment['MARONA_RUNTIME_URL'] ?? 'https://edge.marona.ai',
  );
  try {
    final agent = Agent(
      name: 'Document Assistant',
      model:
          Platform.environment['MARONA_MODEL'] ??
          'marona/qwen-qwen3.8-max-0902',
      instructions: 'Answer clearly and concisely.',
      toolChoice: 'none',
    );
    Object input = 'Reply with exactly OK.';
    if (args.isNotEmpty) {
      final file = File(args.first);
      final extension = file.path.split('.').last.toLowerCase();
      final mime = {
        'png': 'image/png',
        'jpg': 'image/jpeg',
        'jpeg': 'image/jpeg',
      }[extension];
      if (mime == null) throw ArgumentError('Use a PNG or JPEG image.');
      final dataUrl =
          'data:$mime;base64,${base64Encode(await file.readAsBytes())}';
      input = [
        {
          'role': 'user',
          'content': [
            {
              'type': 'input_text',
              'text': 'Describe this image and transcribe any visible text.',
            },
            {'type': 'input_image', 'image_url': dataUrl},
          ],
        },
      ];
    }
    final result = await Runner.run(
      agent,
      input,
      userId: 'example-user',
      sessionId: 'example-session',
    );
    print(result.output);
  } finally {
    marona.close();
  }
}
dart run example/agent_example.dart
dart run example/agent_example.dart image.png

Encode actual file bytes with standard Base64. Image and file blocks accept raw Base64 in image_data / file_data, or complete matching data URLs. Do not encode a path, encode twice, or send placeholder data. Remote URLs must be reachable by the runtime. PDF, audio and realtime support depend on the selected model; render PDF pages to images when native PDF is unavailable.

Structured output through Agent

The following fragment uses the authenticated client from the quickstart. documentInput is your text or document message input.

final agent = Agent(
  name: 'Document Reader',
  model: 'marona/qwen-qwen3.8-max-0902',
  instructions: 'Extract the document text.',
  outputSchemaStrict: true,
  outputSchema: {
    'type': 'object',
    'properties': {'text': {'type': 'string'}},
    'required': ['text'],
    'additionalProperties': false,
  },
);
final result = await Runner.run(agent, documentInput, userId: 'user-123');
print(result.output);

The explicit strict option asks the provider to enforce the supplied schema; the SDK also validates the final result before returning it. Strict mode requires a compatible model and schema. Declare every object property as required, use nullable values for optional fields, and set additionalProperties to false. Unsupported model capabilities or invalid output produce errors; they do not silently fall back to unstructured text. Input schemas, function tool schemas, guardrails, dynamic instructions and lifecycle hooks are also supported.

Apps and user connections

final page = await marona.apps.list(userId: 'user-123', limit: 20);
final action = await marona.apps.connect('calendar', userId: 'user-123');
// Complete any returned authorization_url before calling protected tools.
await marona.apps.disconnect('calendar');

Listing an App does not authorize its protected operations. Follow the returned connection action for the end user. Use hub.connect to expose a scoped set of App or Skill capabilities to an Agent; Apps authorization and Hub tool discovery are separate operations.

A2A collaboration and serving

import 'dart:io';
import 'package:marona/marona.dart';

final peer = A2APeer(name: 'reviewer', url: 'https://reviewer.example.com');
final agent = Agent(name: 'Coordinator', peers: [peer]);
final server = A2AServer(
  agent: agent,
  url: 'https://coordinator.example.com',
  skills: [{'id': 'review', 'name': 'Review', 'description': 'Review a document'}],
  apiKey: Platform.environment['A2A_SERVER_KEY'],
  taskStore: A2ATaskStore(directory: './data/a2a-tasks'),
);
await server.listen(host: '127.0.0.1', port: 8100);
// Call await server.close() during graceful shutdown.

Peers support Agent Card discovery, REST/JSON-RPC messages, task retrieval, cancellation, continuation and streamed task events. Servers persist task state. Use explicit credentials, restricted skills, HTTPS, and an appropriate durable task directory for production. Local JSON stores are for a single service instance; multi-instance deployments require coordinated task storage.

Server hosting requires Dart IO. Push notifications are not implemented.

Execution and errors

Use Runner.stream for streamed Agent events and RealtimeRunner for a live session. Delegation and handoffs use explicit Agent graphs. Set execution limits and validate permissions before tools with side effects; cancellation cannot roll back an operation that has already executed.

Inspect the canonical error code, HTTP status, request ID and retry metadata. Correct invalid input and authorization errors before retrying. Use bounded retries for transient failures. Never include credentials or document content in error reports.

See Platform documentation for language specific examples and migration guidance. These files are generated from docs/client-sdk-guides.json; verify them with python scripts/sync_client_sdk_docs.py --check.

Libraries

marona