Skip to content

Dart SDK release#105

Merged
sawradip merged 4 commits into
mainfrom
rad/dart_sdk
Nov 24, 2025
Merged

Dart SDK release#105
sawradip merged 4 commits into
mainfrom
rad/dart_sdk

Conversation

@RadeenXALNW
Copy link
Copy Markdown
Collaborator

@RadeenXALNW RadeenXALNW commented Nov 24, 2025

Summary

Adds the RunAgent Dart SDK to the main README, including badges and code examples alongside the existing Python, JavaScript, Rust, and Go SDKs.

Changes

  • ✅ Added Dart SDK column to the SDK badges table with:
    • GitHub repository link (runagent-dart)
    • pub.dev downloads badge
    • pub.dev version badge
  • ✅ Added Dart SDK code example showing:
    • Client initialization with RunAgentClient.create()
    • Non-streaming execution with client.run()
    • Streaming execution with client.runStream()
  • ✅ Updated multi-language SDK description to include Dart

Badge Status

The pub.dev badges will display automatically once the package is published to pub.dev. The badge URLs are correct and will work after publishing runagent version 0.1.41.

Related



<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

* **New Features**
  * Added official Dart/Flutter SDK with support for local and remote agent execution, streaming capabilities, and comprehensive error handling.
  * Introduced Journalist Agent example demonstrating AI-powered article generation with both Python backend and Dart client implementation.

* **Documentation**
  * Updated README with Dart SDK information and examples across all language sections.
  * Added comprehensive guides for Dart SDK setup, deployment, and testing.

<sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 24, 2025

Walkthrough

This PR introduces a complete Dart/Flutter SDK for RunAgent with REST and WebSocket clients, comprehensive error handling, and type definitions. It adds a journalist agent example with Dart support and updates core documentation to reflect Dart availability across all SDKs.

Changes

Cohort / File(s) Summary
Documentation and Configuration Updates
.gitignore, README.md
Removed lib/ from gitignore; added Dart SDK entry, badge, code examples, and client usage documentation to README.
Journalist Agent - Python Backend
examples/journalist_agent/agent/main.py, examples/journalist_agent/agent/requirements.txt, examples/journalist_agent/agent/runagent.config.json
New journalist team workflow with Researcher and Writer agents, streaming and non-streaming entrypoints, and runagent configuration for Dart SDK deployment.
Journalist Agent - Dart SDK
examples/journalist_agent/dart_sdk/*
Dart client implementation for journalist agent, including pubspec.yaml, README documentation, main.dart entry point, and generated .dart_tool package metadata.
RunAgent Dart SDK - Core Client
runagent-dart/lib/src/client/rest_client.dart, runagent-dart/lib/src/client/socket_client.dart, runagent-dart/lib/src/client/runagent_client.dart
REST and WebSocket clients for agent communication; RunAgentClient factory for local/remote initialization, architecture validation, run/streaming execution, and payload deserialization.
RunAgent Dart SDK - Error Handling
runagent-dart/lib/src/errors/errors.dart
Error taxonomy with base RunAgentError and seven specialized subclasses (AuthenticationError, PermissionError, ConnectionError, ValidationError, ServerError, UnknownError, RunAgentExecutionError); centralized ErrorCodes constants.
RunAgent Dart SDK - Types and Configuration
runagent-dart/lib/src/types/types.dart, runagent-dart/lib/src/utils/config.dart, runagent-dart/lib/src/utils/constants.dart
Type definitions (RunAgentClientConfig, AgentArchitecture, EntryPoint, RunInput) with JSON deserialization; ConfigUtils for environment-based configuration; RunAgentConstants for defaults and env var names.
RunAgent Dart SDK - Public API and Examples
runagent-dart/lib/runagent.dart, runagent-dart/example/*.dart
Public library export surface; three example programs demonstrating basic, local, and streaming RunAgent usage.
RunAgent Dart SDK - Tests and Documentation
runagent-dart/test/runagent_types_test.dart, runagent-dart/CHANGELOG.md, runagent-dart/LICENSE, runagent-dart/PUBLISH.md, runagent-dart/README.md, runagent-dart/pubspec.yaml
Unit tests for types; comprehensive SDK documentation, publishing workflow, changelog, and license; Dart package manifest.
RunAgent Dart SDK - Build Artifacts
runagent-dart/.dart_tool/package_config.json, runagent-dart/.dart_tool/package_graph.json, test_scripts/dart/test_agno/.dart_tool/*
Generated Pub package configuration and dependency graphs for runagent-dart and test_agno projects.
Test Fixtures - Agno Integration
test_scripts/dart/test_agno/lib/main.dart, test_scripts/dart/test_agno/pubspec.yaml, test_scripts/dart/test_agno/README.md
Test harness for Dart SDK with Agno agent integration, streaming workflow example, and setup documentation.

Sequence Diagram(s)

sequenceDiagram
    participant App
    participant RunAgentClient
    participant RestClient
    participant SocketClient
    participant RemoteAgent

    App->>RunAgentClient: create(config)
    activate RunAgentClient
    alt config.local == false (Remote)
        RunAgentClient->>RestClient: new(baseUrl, apiKey, isLocal=false)
        RunAgentClient->>SocketClient: new(baseSocketUrl, apiKey, isLocal=false)
    else config.local == true (Local)
        RunAgentClient->>RestClient: new(baseUrl, apiKey, isLocal=true)
        RunAgentClient->>SocketClient: new(baseSocketUrl, apiKey, isLocal=true)
    end
    RunAgentClient->>RestClient: getAgentArchitecture(agentId)
    RestClient->>RemoteAgent: GET /agents/{agentId}/architecture
    RestClient-->>RunAgentClient: AgentArchitecture
    RunAgentClient->>RunAgentClient: validate entrypointTag exists
    deactivate RunAgentClient
    RunAgentClient-->>App: RunAgentClient instance

    App->>RunAgentClient: run(inputKwargs)
    activate RunAgentClient
    RunAgentClient->>RestClient: runAgent(agentId, entrypointTag, args, kwargs, timeout)
    RestClient->>RemoteAgent: POST /run<br/>(with auth header if remote)
    RestClient->>RestClient: _translateHttpError if error
    RestClient-->>RunAgentClient: response payload
    RunAgentClient->>RunAgentClient: _deserializeObject(payload)
    deactivate RunAgentClient
    RunAgentClient-->>App: dynamic result

    App->>RunAgentClient: runStream(inputKwargs)
    activate RunAgentClient
    RunAgentClient->>SocketClient: runStream(agentId, entrypointTag, args, kwargs)
    activate SocketClient
    SocketClient->>RemoteAgent: WebSocket upgrade<br/>(ws/wss with auth if remote)
    SocketClient->>RemoteAgent: send {entrypoint_tag, input_args, input_kwargs}
    loop stream messages
        RemoteAgent->>SocketClient: {type: 'data', payload: chunk}
        SocketClient->>SocketClient: _deserializeChunk(payload)
        SocketClient-->>RunAgentClient: yield deserialized chunk
        RunAgentClient-->>App: yield to Stream
    end
    RemoteAgent->>SocketClient: {type: 'status', status: 'stream_completed'}
    SocketClient->>SocketClient: close stream
    deactivate SocketClient
    deactivate RunAgentClient
Loading
sequenceDiagram
    participant Client as RestClient
    participant HTTP as HTTP Layer
    participant Server as Remote Server

    Client->>Client: runAgent(...payload)
    alt Remote Mode (isLocal=false)
        Client->>Client: verify apiKey exists
        Client->>Client: throw AuthenticationError if missing
    end
    Client->>Client: build headers<br/>(Content-Type, User-Agent, Auth if remote)
    Client->>HTTP: POST baseUrl/run
    alt Success (200)
        HTTP-->>Client: response body
        Client->>Client: JSON decode response
        Client-->>Client: return Map<String, dynamic>
    else 401/403
        HTTP-->>Client: error response
        Client->>Client: _translateHttpError → AuthenticationError
    else 500+
        HTTP-->>Client: error response
        Client->>Client: _translateHttpError → ServerError
    else 4xx
        HTTP-->>Client: error response
        Client->>Client: _translateHttpError → ValidationError
    else Timeout
        HTTP-->>Client: TimeoutException
        Client->>Client: throw ConnectionError
    else Connection Error
        HTTP-->>Client: exception
        Client->>Client: throw ConnectionError
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

  • Rest client HTTP error handling and translation (rest_client.dart): Requires careful review of status code mappings, error payload parsing, and authentication logic for remote vs local modes.
  • Socket client streaming and deserialization (socket_client.dart): Streaming message handling, structured data deserialization, and error propagation from WebSocket need close inspection.
  • RunAgentClient initialization and lifecycle (runagent_client.dart): Factory pattern, architecture validation, entrypoint resolution, and payload normalization across legacy and envelope formats warrant detailed review.
  • Error taxonomy consistency (errors.dart): Verify all error subclasses are used consistently across clients and that error codes align with usage in the codebase.
  • Type deserialization and JSON handling (types.dart): Ensure AgentArchitecture and EntryPoint fromJson factories handle malformed or missing fields robustly.
  • Configuration resolution precedence (config.dart): Environment variable fallbacks and precedence logic should be verified for correctness.
  • Heterogeneous file composition: Mix of logic files (clients, errors, types), utility modules (config, constants), configuration files (pubspec.yaml, runagent.config.json), documentation, and generated Dart tool metadata increases cognitive load.

Possibly related PRs

  • Sawra/util fix #85: Implements structured-response deserialization and error-shape handling aligned with rest_client/socket_client deserialization and error taxonomy in this PR.

Suggested reviewers

  • sawradip

Poem

🐰 A Dart flies swift through the autumn breeze,
REST and Streams dance with ease,
Errors caught in structured grace,
RunAgent hops to the next place!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Dart SDK release' directly describes the main change—this PR adds the RunAgent Dart SDK (version 0.1.41) with comprehensive documentation, examples, and library files across multiple new directories and configuration files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch rad/dart_sdk

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

♻️ Duplicate comments (1)
examples/journalist_agent/dart_sdk/.dart_tool/package_config.json (1)

1-106: Exclude generated .dart_tool files and avoid exposing local paths.

This auto-generated file should not be committed to version control. Additionally, it exposes local file system paths (e.g., /home/azureuser/) which could be a privacy concern.

🧹 Nitpick comments (12)
examples/journalist_agent/dart_sdk/Readme.md (1)

34-34: Add explicit host/port defaults documentation.

Line 34 states the defaults are 127.0.0.1:8451, but these should be validated against the actual RunAgent local server implementation and explicitly documented in the Dart SDK example code for clarity.

Consider adding a code comment or configuration example showing exactly how these defaults are overridden in test_dart/lib/main.dart:

// Example: Set host/port for local development
final client = RunAgentClient.create(
  host: '127.0.0.1',
  port: 8451,
  local: true, // Overrides cloud authentication
);
examples/journalist_agent/agent/requirements.txt (2)

1-1: Remove trailing whitespace.

Lines 1 and 4 contain trailing whitespace after the package names. This should be removed for consistency and to avoid potential issues with some tooling.

Also applies to: 4-4


1-6: Consider pinning dependency versions for reproducibility.

Most dependencies lack version constraints, which can lead to non-reproducible builds and potential breakage from incompatible updates. Consider using exact versions or at minimum version ranges for all dependencies.

runagent-dart/lib/src/types/types.dart (2)

44-67: Consider removing the redundant factory method.

The RunAgentClientConfig.create() factory method has an identical signature and implementation to the default constructor. In Dart, this duplication is unnecessary unless the factory adds value (validation, defaults computation, etc.).

-  /// Create a config with required fields
-  factory RunAgentClientConfig.create({
-    required String agentId,
-    required String entrypointTag,
-    bool? local,
-    String? host,
-    int? port,
-    String? apiKey,
-    String? baseUrl,
-    Map<String, dynamic>? extraParams,
-    bool? enableRegistry,
-  }) {
-    return RunAgentClientConfig(
-      agentId: agentId,
-      entrypointTag: entrypointTag,
-      local: local,
-      host: host,
-      port: port,
-      apiKey: apiKey,
-      baseUrl: baseUrl,
-      extraParams: extraParams,
-      enableRegistry: enableRegistry,
-    );
-  }

Alternatively, if the factory is needed for API consistency with other SDKs, keep it but add a comment explaining why it exists.


138-146: Refactor toJson() to accept entrypointTag as a parameter.

The toJson() method includes a placeholder empty string for entrypoint_tag with a comment indicating it will be set by the client. This design is fragile and error-prone, as it's easy to forget to update the map after serialization.

Refactor to accept the tag as a parameter:

-  Map<String, dynamic> toJson() {
+  Map<String, dynamic> toJson(String entrypointTag) {
     return {
-      'entrypoint_tag': '', // Will be set by client
+      'entrypoint_tag': entrypointTag,
       'input_args': inputArgs,
       'input_kwargs': inputKwargs,
       'timeout_seconds': timeoutSeconds,
       'async_execution': asyncExecution,
     };
   }

This makes the required parameter explicit and prevents serialization with incomplete data.

test_scripts/dart/test_agno/.dart_tool/package_graph.json (1)

1-124: Consider whether .dart_tool/ files should be committed.

The package_graph.json file is generated by Dart tooling and resides in the .dart_tool/ directory, which is typically listed in .gitignore. While some projects commit these files for reproducibility, the standard practice is to exclude them and let developers regenerate them locally via dart pub get.

Verify whether .dart_tool/ is already in .gitignore:

#!/bin/bash
# Description: Check if .dart_tool is gitignored

# Check for .gitignore entries
rg -n '\.dart_tool' .gitignore

If not present, consider adding .dart_tool/ to .gitignore to follow Dart conventions.

runagent-dart/example/basic_example.dart (1)

7-13: Consider explicit null handling for the API key.

The Platform.environment['RUNAGENT_API_KEY'] can return null, which is passed to the apiKey parameter. While this may be intentional (relying on SDK defaults or alternative auth mechanisms), consider adding an explicit null check with a helpful error message for clarity.

Optional improvement:

   final client = await RunAgentClient.create(
     RunAgentClientConfig.create(
       agentId: 'YOUR_AGENT_ID',
       entrypointTag: 'generic',
-      apiKey: Platform.environment['RUNAGENT_API_KEY'],
+      apiKey: Platform.environment['RUNAGENT_API_KEY'] ?? 
+        (throw StateError('RUNAGENT_API_KEY environment variable is required')),
     ),
   );
examples/journalist_agent/dart_sdk/lib/main.dart (1)

6-12: Add trailing comma for consistent Dart formatting.

Dart style guidelines recommend adding trailing commas to function arguments for better formatting and readability, especially in nested constructor calls.

Apply this diff:

     final client = await RunAgentClient.create(
       RunAgentClientConfig.create(
         agentId: '9fac4988-d88e-4d6c-994c-7495c11de8b9',
-        entrypointTag: 'create_article'
+        entrypointTag: 'create_article',
         // local: true, host: '127.0.0.1', port: 8451,
       ),
     );
test_scripts/dart/test_agno/lib/main.dart (1)

1-31: Consider removing the commented-out code.

The large commented-out non-streaming example (lines 1-31) adds clutter. If this alternative implementation is needed for reference, consider moving it to a separate example file or documenting it in the README instead.

Apply this diff to remove the commented block:

-// // async version non-streaming
-// import 'dart:io';
-// import 'package:runagent/runagent.dart';
-
-// Future<void> main() async {
-//   try {
-//     // Direct config construction
-//     final client = await RunAgentClient.create(
-//       RunAgentClientConfig.create(
-//         agentId: 'ae29bd73-b3d3-42c8-a98f-5d7aec7ee919',
-//         entrypointTag: 'agno_print_response',
-//       ),
-//     );
-    
-//     final response = await client.run({
-//       'prompt': 'which is better toyota or land rover',
-//     });
-    
-//     // Response is a Map, not a String
-//     print('Response: $response');  // <-- Added semicolon here
-//   } catch (e) {
-//     if (e is RunAgentError) {
-//       print('Error: ${e.message}');
-//       if (e.suggestion != null) {
-//         print('Suggestion: ${e.suggestion}');
-//       }
-//     } else {
-//       print('Unexpected error: $e');
-//     }
-//   }
-// }
-
 // ******************************Streaming Part with agno****************************************
 // async version streaming (Flutter/Dart idiomatic approach)
runagent-dart/lib/src/utils/constants.dart (1)

35-36: Avoid hard‑coding SDK version in userAgent()

Hard‑coding runagent-dart/0.1.0 here will drift from the package version over time. Consider centralizing the SDK version in a single constant and reusing it (or wiring it from build/pubspec metadata) so bumping the package version doesn’t require hunting this string.

 class RunAgentConstants {
+  /// SDK version (keep in sync with pubspec.yaml)
+  static const String sdkVersion = '0.1.0';
@@
   /// User agent string
-  static String userAgent() => 'runagent-dart/0.1.0';
+  static String userAgent() => 'runagent-dart/$sdkVersion';
 }
runagent-dart/lib/src/errors/errors.dart (1)

31-48: Deduplicate error-code strings between subclasses and ErrorCodes

AuthenticationError, PermissionError, etc. each hard‑code their code strings, while ErrorCodes defines the same values again. This duplication can easily drift if codes are ever renamed.

Using ErrorCodes directly in the subclass constructors keeps everything in one place and avoids subtle mismatches.

 class AuthenticationError extends RunAgentError {
   AuthenticationError({
     required super.message,
     super.suggestion,
     super.details,
-  }) : super(code: 'AUTHENTICATION_ERROR');
+  }) : super(code: ErrorCodes.authenticationError);
 }
@@
 class PermissionError extends RunAgentError {
   PermissionError({
     required super.message,
     super.suggestion,
     super.details,
-  }) : super(code: 'PERMISSION_ERROR');
+  }) : super(code: ErrorCodes.permissionError);
 }
@@
 class ConnectionError extends RunAgentError {
   ConnectionError({
     required super.message,
     super.suggestion,
     super.details,
-  }) : super(code: 'CONNECTION_ERROR');
+  }) : super(code: ErrorCodes.connectionError);
 }
@@
 class ValidationError extends RunAgentError {
   ValidationError({
     required super.message,
     super.suggestion,
     super.details,
-  }) : super(code: 'VALIDATION_ERROR');
+  }) : super(code: ErrorCodes.validationError);
 }
@@
 class ServerError extends RunAgentError {
   ServerError({
     required super.message,
     super.suggestion,
     super.details,
-  }) : super(code: 'SERVER_ERROR');
+  }) : super(code: ErrorCodes.serverError);
 }
@@
 class UnknownError extends RunAgentError {
   UnknownError({
     required super.message,
     super.suggestion,
     super.details,
-  }) : super(code: 'UNKNOWN_ERROR');
+  }) : super(code: ErrorCodes.unknownError);
 }

Also applies to: 85-98

runagent-dart/lib/src/client/runagent_client.dart (1)

183-214: Factor out shared architecture-loading logic to avoid duplication

_initializeArchitecture() and getAgentArchitecture() both implement nearly identical logic for calling restClient.getAgentArchitecture, handling the envelope/legacy formats, and populating _architecture. This duplication is easy to drift if you tweak one path and forget the other.

Consider extracting a single private helper that loads and normalizes the architecture once, and reuse it from both places; then _initializeArchitecture() can focus purely on entrypoint validation.

 class RunAgentClient {
@@
-  Future<void> _initializeArchitecture() async {
-    final architectureJson = await restClient.getAgentArchitecture(agentId);
-    
-    // Handle envelope format
-    if (architectureJson.containsKey('success')) {
-      final success = architectureJson['success'] as bool?;
-      if (success == false) {
-        final error = architectureJson['error'];
-        if (error is Map<String, dynamic>) {
-          final errorMessage = error['message'];
-          final errorCode = error['code'];
-          throw RunAgentExecutionError(
-            code: errorCode is String ? errorCode : ErrorCodes.serverError,
-            message: errorMessage is String ? errorMessage : 'Failed to retrieve agent architecture',
-            suggestion: error['suggestion'] is String ? error['suggestion'] : null,
-            details: error['details'] is Map<String, dynamic> ? error['details'] : null,
-          );
-        }
-        final message = architectureJson['message'];
-        throw ServerError(
-          message: message is String ? message : 'Failed to retrieve agent architecture',
-        );
-      }
-      
-      final data = architectureJson['data'] as Map<String, dynamic>?;
-      if (data != null) {
-        _architecture = AgentArchitecture.fromJson(data);
-      }
-    } else {
-      // Legacy format
-      _architecture = AgentArchitecture.fromJson(architectureJson);
-    }
-
-    // Validate entrypoint exists
+  Future<void> _loadArchitectureIfNeeded() async {
+    if (_architecture != null) return;
+
+    final architectureJson = await restClient.getAgentArchitecture(agentId);
+
+    if (architectureJson.containsKey('success')) {
+      final success = architectureJson['success'] as bool?;
+      if (success == false) {
+        final error = architectureJson['error'];
+        if (error is Map<String, dynamic>) {
+          final errorMessage = error['message'];
+          final errorCode = error['code'];
+          throw RunAgentExecutionError(
+            code: errorCode is String ? errorCode : ErrorCodes.serverError,
+            message: errorMessage is String ? errorMessage : 'Failed to retrieve agent architecture',
+            suggestion: error['suggestion'] is String ? error['suggestion'] : null,
+            details: error['details'] is Map<String, dynamic> ? error['details'] : null,
+          );
+        }
+        final message = architectureJson['message'];
+        throw ServerError(
+          message: message is String ? message : 'Failed to retrieve agent architecture',
+        );
+      }
+
+      final data = architectureJson['data'] as Map<String, dynamic>?;
+      if (data != null) {
+        _architecture = AgentArchitecture.fromJson(data);
+      }
+    } else {
+      _architecture = AgentArchitecture.fromJson(architectureJson);
+    }
+
     if (_architecture == null || _architecture!.entrypoints.isEmpty) {
       throw ValidationError(
         message: 'Architecture missing entrypoints',
         suggestion: 'Redeploy the agent with entrypoints configured',
       );
     }
-    
+  }
+
+  Future<void> _initializeArchitecture() async {
+    await _loadArchitectureIfNeeded();
+
+    // Validate entrypoint exists
     final found = _architecture!.entrypoints.any(
       (ep) => ep.tag == entrypointTag,
     );
@@
   Future<AgentArchitecture> getAgentArchitecture() async {
-    if (_architecture != null) {
-      return _architecture!;
-    }
-
-    final architectureJson = await restClient.getAgentArchitecture(agentId);
-    
-    // Handle envelope format
-    if (architectureJson.containsKey('success')) {
-      final success = architectureJson['success'] as bool?;
-      if (success == false) {
-        final error = architectureJson['error'];
-        if (error is Map<String, dynamic>) {
-          final errorMessage = error['message'];
-          final errorCode = error['code'];
-          throw RunAgentExecutionError(
-            code: errorCode is String ? errorCode : ErrorCodes.serverError,
-            message: errorMessage is String ? errorMessage : 'Failed to retrieve agent architecture',
-            suggestion: error['suggestion'] is String ? error['suggestion'] : null,
-            details: error['details'] is Map<String, dynamic> ? error['details'] : null,
-          );
-        }
-        final message = architectureJson['message'];
-        throw ServerError(
-          message: message is String ? message : 'Failed to retrieve agent architecture',
-        );
-      }
-      
-      final data = architectureJson['data'] as Map<String, dynamic>?;
-      if (data != null) {
-        _architecture = AgentArchitecture.fromJson(data);
-      }
-    } else {
-      // Legacy format
-      _architecture = AgentArchitecture.fromJson(architectureJson);
-    }
-
-    if (_architecture == null || _architecture!.entrypoints.isEmpty) {
-      throw ValidationError(
-        message: 'Architecture missing entrypoints',
-        suggestion: 'Redeploy the agent with entrypoints configured',
-      );
-    }
-
+    await _loadArchitectureIfNeeded();
     return _architecture!;
   }

Also applies to: 381-411

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 421bd1f and 2aa1c3d.

📒 Files selected for processing (35)
  • .gitignore (0 hunks)
  • README.md (5 hunks)
  • examples/journalist_agent/agent/main.py (1 hunks)
  • examples/journalist_agent/agent/requirements.txt (1 hunks)
  • examples/journalist_agent/agent/runagent.config.json (1 hunks)
  • examples/journalist_agent/dart_sdk/.dart_tool/package_config.json (1 hunks)
  • examples/journalist_agent/dart_sdk/.dart_tool/package_graph.json (1 hunks)
  • examples/journalist_agent/dart_sdk/Readme.md (1 hunks)
  • examples/journalist_agent/dart_sdk/lib/main.dart (1 hunks)
  • examples/journalist_agent/dart_sdk/pubspec.yaml (1 hunks)
  • runagent-dart/.dart_tool/package_config.json (1 hunks)
  • runagent-dart/.dart_tool/package_graph.json (1 hunks)
  • runagent-dart/CHANGELOG.md (1 hunks)
  • runagent-dart/LICENSE (1 hunks)
  • runagent-dart/PUBLISH.md (1 hunks)
  • runagent-dart/README.md (1 hunks)
  • runagent-dart/example/basic_example.dart (1 hunks)
  • runagent-dart/example/local_example.dart (1 hunks)
  • runagent-dart/example/streaming_example.dart (1 hunks)
  • runagent-dart/lib/runagent.dart (1 hunks)
  • runagent-dart/lib/src/client/rest_client.dart (1 hunks)
  • runagent-dart/lib/src/client/runagent_client.dart (1 hunks)
  • runagent-dart/lib/src/client/socket_client.dart (1 hunks)
  • runagent-dart/lib/src/errors/errors.dart (1 hunks)
  • runagent-dart/lib/src/types/types.dart (1 hunks)
  • runagent-dart/lib/src/utils/config.dart (1 hunks)
  • runagent-dart/lib/src/utils/constants.dart (1 hunks)
  • runagent-dart/pubspec.yaml (1 hunks)
  • runagent-dart/test/runagent_types_test.dart (1 hunks)
  • test/runagent_types_test.dart (1 hunks)
  • test_scripts/dart/test_agno/.dart_tool/package_config.json (1 hunks)
  • test_scripts/dart/test_agno/.dart_tool/package_graph.json (1 hunks)
  • test_scripts/dart/test_agno/README.md (1 hunks)
  • test_scripts/dart/test_agno/lib/main.dart (1 hunks)
  • test_scripts/dart/test_agno/pubspec.yaml (1 hunks)
💤 Files with no reviewable changes (1)
  • .gitignore
🔇 Additional comments (24)
examples/journalist_agent/dart_sdk/Readme.md (1)

63-73: No issues found — Dart SDK method signatures verified.

The run() and runStream() methods exist and their signatures correctly match the documented examples:

  • run() (line 246) accepts Map<String, dynamic>? and returns Future<dynamic>, supporting the await client.run({'topic': 'AI developments'}) pattern.
  • runStream() (line 350) accepts Map<String, dynamic>? and returns Stream<dynamic>, supporting the await for pattern shown in the documentation.
README.md (3)

29-29: LGTM!

The Dart SDK badge additions are properly structured and consistent with the existing Python, JavaScript, Rust, and Go SDK columns. The pub.dev badge URLs follow the correct format and will display automatically once the package is published.

Also applies to: 54-58, 75-79


233-233: LGTM!

The description correctly includes Dart in the list of supported SDK languages.


237-242: LGTM!

The Dart SDK code example is well-structured and demonstrates key features:

  • Client initialization with configuration
  • Non-streaming execution using run()
  • Streaming execution using runStream() with await for

The code uses idiomatic Dart patterns and is consistent with the other SDK examples. The API design is clean and follows Dart conventions.

Also applies to: 397-430

runagent-dart/example/streaming_example.dart (1)

1-33: LGTM!

This streaming example demonstrates best practices:

  • Uses environment variables for sensitive data (API key)
  • Appropriate placeholder for agent ID
  • Proper error handling with specific RunAgentError catching
  • Clear demonstration of the runStream() API with await for
  • Helpful comment about the _stream suffix convention

The code is clean, idiomatic Dart, and serves as a good reference for SDK users.

runagent-dart/pubspec.yaml (1)

9-15: Consider updating dependencies within their allowed constraints.

Pub uses the GitHub Advisory Database for publishing security advisories for Dart and Flutter packages. Your version constraints are working as intended with the caret operator (^), but there are newer compatible versions available:

  • http: 1.1.0 → 1.6.0 (compatible)
  • test: 1.24.0 → 1.28.0 (compatible)

web_socket_channel (2.4.0 → 3.0.3) and lints (3.0.0 → 6.0.0) have major version updates available but would require explicit constraint changes. If you intend to stay current on patch/minor updates, run dart pub upgrade to pull in compatible versions. If no security advisories are reported during dart pub get, your current versions are acceptable.

runagent-dart/PUBLISH.md (2)

1-105: LGTM! Clear and comprehensive publishing guide.

The publishing workflow is well-structured and follows Dart/pub.dev best practices. The step-by-step instructions with command examples will be helpful for maintainers.


42-45: All example files are present and correctly referenced.

Verification confirms that the three example files referenced in lines 42-45 of PUBLISH.md exist and are properly located in runagent-dart/example/. The dart run commands will execute as documented.

examples/journalist_agent/agent/main.py (3)

1-9: LGTM! Clean imports and model configuration.

The imports and model string format are appropriate for the agno framework.


11-50: LGTM! Well-structured multi-agent team.

The journalist team configuration is well-designed with clear role separation between Researcher and Writer agents. The instructions are detailed and appropriate for each role.


67-70: LGTM! Streaming implementation handles chunk variations appropriately.

The streaming function correctly yields chunks and includes defensive handling for chunks with or without a content attribute.

examples/journalist_agent/agent/runagent.config.json (1)

13-32: LGTM! Entrypoints correctly reference the Python functions.

The entrypoints configuration correctly maps to the create_article and create_article_stream functions defined in main.py, and the auth settings are properly configured.

test_scripts/dart/test_agno/pubspec.yaml (1)

1-10: LGTM! Proper dependency declaration.

The pubspec correctly uses a version constraint for the runagent dependency, making it portable and suitable for published use. The version constraint ^0.1.41 aligns with the SDK version mentioned in the PR objectives.

runagent-dart/CHANGELOG.md (1)

10-26: LGTM! Comprehensive changelog entries.

The changelog clearly documents all major features and capabilities added in the initial release, following the Keep a Changelog format.

runagent-dart/README.md (1)

1-228: LGTM! Comprehensive SDK documentation.

The README provides clear, well-organized documentation covering all essential aspects: installation options, configuration precedence, local vs remote usage, streaming, error handling, and troubleshooting. The examples are practical and the error taxonomy table is particularly helpful.

runagent-dart/example/local_example.dart (1)

1-34: LGTM! Well-structured local agent example.

The example clearly demonstrates local agent usage with appropriate configuration (local flag, host, port) and proper error handling.

test_scripts/dart/test_agno/README.md (1)

1-44: LGTM! Clear test script documentation.

The README provides straightforward setup and usage instructions with helpful configuration examples for both remote and local agents.

runagent-dart/test/runagent_types_test.dart (1)

4-74: Type tests look consistent and well‑targeted

The coverage for RunAgentClientConfig.create, AgentArchitecture.fromJson, and RunInput.toJson matches the described semantics and asserts the right normalization and JSON keys/values. No issues spotted here.

runagent-dart/lib/runagent.dart (1)

1-11: Public SDK facade is clean and cohesive

The runagent library declaration plus consolidated exports of client, errors, types, config, and constants make for a straightforward public entrypoint. Looks good.

runagent-dart/lib/src/utils/config.dart (1)

4-69: Env configuration helpers are straightforward and side‑effect free

The getters and helper functions (resolveBool, firstNonEmpty, firstNonZero) handle nulls and precedence cleanly, and the behavior matches the inline docs. No issues from a correctness standpoint.

runagent-dart/lib/src/client/socket_client.dart (1)

19-216: Streaming client logic and cleanup look solid

URL construction, authentication checks, message routing (error/status/data/fallback), and the finally‑based channel close are all wired up coherently. Error paths correctly surface RunAgentExecutionError vs connection issues. Looks good overall.

runagent-dart/lib/src/client/rest_client.dart (1)

19-188: REST client behavior and error mapping are consistent

getAgentArchitecture, runAgent, and healthCheck all follow a clear pattern, and _translateHttpError/_parseApiError give you predictable, typed errors for non‑200 responses while treating transport/timeout issues as connection errors. The auth guard for remote runAgent also prevents silent 401s. No blocking issues here.

test/runagent_types_test.dart (1)

76-150: Duplicate test suite and second main() definition must be removed

This file contains a full duplicate copy of the test suite, including a second main() function. That will fail to compile and is redundant even if it did.

Recommend keeping only one copy of the tests and a single main():

@@
-}
-import 'package:runagent/runagent.dart';
-import 'package:test/test.dart';
-
-void main() {
-  group('RunAgentClientConfig', () {
-    test('create factory mirrors constructor arguments', () {
-      final config = RunAgentClientConfig.create(
-        agentId: 'agent-123',
-        entrypointTag: 'article_create',
-        local: true,
-        host: '127.0.0.1',
-        port: 8451,
-        apiKey: 'secret',
-        baseUrl: 'https://example.com',
-        extraParams: {'foo': 'bar'},
-        enableRegistry: false,
-      );
-
-      expect(config.agentId, 'agent-123');
-      expect(config.entrypointTag, 'article_create');
-      expect(config.local, isTrue);
-      expect(config.host, '127.0.0.1');
-      expect(config.port, 8451);
-      expect(config.apiKey, 'secret');
-      expect(config.baseUrl, 'https://example.com');
-      expect(config.extraParams, {'foo': 'bar'});
-      expect(config.enableRegistry, isFalse);
-    });
-  });
-
-  group('AgentArchitecture', () {
-    test('fromJson normalizes agentId and entrypoints', () {
-      final architecture = AgentArchitecture.fromJson({
-        'agent_id': 42,
-        'entrypoints': [
-          {
-            'tag': 'article_create',
-            'file': 'main.py',
-            'description': 'Create article',
-          },
-          {
-            'tag': 123,
-            'module': 'agents.writer',
-          },
-        ],
-      });
-
-      expect(architecture.agentId, '42');
-      expect(architecture.entrypoints, hasLength(2));
-      expect(architecture.entrypoints.first.tag, 'article_create');
-      expect(architecture.entrypoints.first.file, 'main.py');
-      expect(architecture.entrypoints.last.tag, '123');
-      expect(architecture.entrypoints.last.module, 'agents.writer');
-    });
-  });
-
-  group('RunInput', () {
-    test('toJson includes defaults and provided values', () {
-      final runInput = RunInput(
-        inputArgs: ['foo'],
-        inputKwargs: {'bar': 1},
-        timeoutSeconds: 120,
-        asyncExecution: true,
-      );
-
-      final json = runInput.toJson();
-
-      expect(json['entrypoint_tag'], '');
-      expect(json['input_args'], ['foo']);
-      expect(json['input_kwargs'], {'bar': 1});
-      expect(json['timeout_seconds'], 120);
-      expect(json['async_execution'], isTrue);
-    });
-  });
-}
+}

Likely an incorrect or invalid review comment.

runagent-dart/lib/src/client/runagent_client.dart (1)

246-373: Run vs. runStream guardrails and payload handling look solid

The split between run/runWithArgs and runStream/runStreamWithArgs, keyed off the _stream suffix, plus the generator‑object detection and structured payload deserialization, is well thought out. The failure modes produce meaningful ValidationError / RunAgentExecutionError instances with suggestions, which should make debugging SDK usage much easier.

Comment on lines +53 to +64
def create_article(topic: str):
"""
Create a high-quality news article on a given topic

Args:
topic: The topic to write about
"""
response = journalist_team.run(topic, stream=False)
return {
"article": response.content,
"success": True
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Consider removing hardcoded success=True or add error handling.

The success field is always set to True, even if journalist_team.run() might encounter issues. While exceptions would still propagate, this could mislead API consumers who check the success flag.

Consider one of these approaches:

Option 1: Remove the success field entirely (simpler)

 def create_article(topic: str):
     """
     Create a high-quality news article on a given topic
     
     Args:
         topic: The topic to write about
     """
     response = journalist_team.run(topic, stream=False)
-    return {
-        "article": response.content,
-        "success": True
-    }
+    return {"article": response.content}

Option 2: Add proper error handling (if success flag is needed by clients)

 def create_article(topic: str):
     """
     Create a high-quality news article on a given topic
     
     Args:
         topic: The topic to write about
     """
+    try:
-        response = journalist_team.run(topic, stream=False)
-        return {
-            "article": response.content,
-            "success": True
-        }
+        response = journalist_team.run(topic, stream=False)
+        return {
+            "article": response.content,
+            "success": True
+        }
+    except Exception as e:
+        return {
+            "article": "",
+            "success": False,
+            "error": str(e)
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def create_article(topic: str):
"""
Create a high-quality news article on a given topic
Args:
topic: The topic to write about
"""
response = journalist_team.run(topic, stream=False)
return {
"article": response.content,
"success": True
}
def create_article(topic: str):
"""
Create a high-quality news article on a given topic
Args:
topic: The topic to write about
"""
response = journalist_team.run(topic, stream=False)
return {"article": response.content}
Suggested change
def create_article(topic: str):
"""
Create a high-quality news article on a given topic
Args:
topic: The topic to write about
"""
response = journalist_team.run(topic, stream=False)
return {
"article": response.content,
"success": True
}
def create_article(topic: str):
"""
Create a high-quality news article on a given topic
Args:
topic: The topic to write about
"""
try:
response = journalist_team.run(topic, stream=False)
return {
"article": response.content,
"success": True
}
except Exception as e:
return {
"article": "",
"success": False,
"error": str(e)
}
🤖 Prompt for AI Agents
In examples/journalist_agent/agent/main.py around lines 53 to 64, the returned
dict always sets "success": True which can mislead callers if
journalist_team.run() fails; either remove the success field entirely, or wrap
the call in a try/except that returns {"article": response.content, "success":
True} on success and {"article": None, "success": False, "error": str(e)} (or
similar minimal error info) on exception (or re-raise after logging) so the
success flag accurately reflects outcome.

Comment on lines +8 to +12
"template_source": {
"repo_url": "https://github.com/runagent-dev/runagent.git",
"author": "runagent-cli",
"path": "/home/azureuser/runagent/examples/journalist_agent/agent"
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove hardcoded absolute path from template_source.

The path field contains a hardcoded absolute path /home/azureuser/runagent/... that is specific to one development environment. This breaks portability and won't work for other users or in CI/CD environments.

Apply this diff to use a relative path or remove the hardcoded path:

   "template_source": {
     "repo_url": "https://github.com/runagent-dev/runagent.git",
     "author": "runagent-cli",
-    "path": "/home/azureuser/runagent/examples/journalist_agent/agent"
+    "path": "examples/journalist_agent/agent"
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"template_source": {
"repo_url": "https://github.com/runagent-dev/runagent.git",
"author": "runagent-cli",
"path": "/home/azureuser/runagent/examples/journalist_agent/agent"
},
"template_source": {
"repo_url": "https://github.com/runagent-dev/runagent.git",
"author": "runagent-cli",
"path": "examples/journalist_agent/agent"
},
🤖 Prompt for AI Agents
In examples/journalist_agent/agent/runagent.config.json around lines 8 to 12,
the template_source.path is a hardcoded absolute path
(/home/azureuser/runagent/...), which breaks portability; replace it with a
relative path (e.g., path relative to the repository root or the examples
directory) or remove the path field entirely so the repo_url and path resolution
logic can use defaults; update the JSON to use a relative value like
"./examples/journalist_agent/agent" or omit the path key, and ensure any code
that consumes this config resolves paths relative to the config file or repo
root.

Comment on lines +1 to +124
{
"roots": [
"test_journalist"
],
"packages": [
{
"name": "test_journalist",
"version": "0.1.0",
"dependencies": [
"runagent"
],
"devDependencies": []
},
{
"name": "runagent",
"version": "0.1.0",
"dependencies": [
"http",
"web_socket_channel"
]
},
{
"name": "web_socket_channel",
"version": "2.4.5",
"dependencies": [
"async",
"crypto",
"stream_channel",
"web"
]
},
{
"name": "web",
"version": "0.5.1",
"dependencies": []
},
{
"name": "stream_channel",
"version": "2.1.4",
"dependencies": [
"async"
]
},
{
"name": "crypto",
"version": "3.0.7",
"dependencies": [
"typed_data"
]
},
{
"name": "typed_data",
"version": "1.4.0",
"dependencies": [
"collection"
]
},
{
"name": "collection",
"version": "1.19.1",
"dependencies": []
},
{
"name": "http",
"version": "1.6.0",
"dependencies": [
"async",
"http_parser",
"meta",
"web"
]
},
{
"name": "http_parser",
"version": "4.1.2",
"dependencies": [
"collection",
"source_span",
"string_scanner",
"typed_data"
]
},
{
"name": "string_scanner",
"version": "1.4.1",
"dependencies": [
"source_span"
]
},
{
"name": "source_span",
"version": "1.10.1",
"dependencies": [
"collection",
"path",
"term_glyph"
]
},
{
"name": "term_glyph",
"version": "1.2.2",
"dependencies": []
},
{
"name": "path",
"version": "1.9.1",
"dependencies": []
},
{
"name": "async",
"version": "2.13.0",
"dependencies": [
"collection",
"meta"
]
},
{
"name": "meta",
"version": "1.17.0",
"dependencies": []
}
],
"configVersion": 1
} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Consider excluding generated .dart_tool files from version control.

The .dart_tool/ directory contains auto-generated Dart tooling files that are typically excluded from version control via .gitignore. These files are regenerated by dart pub get and including them can cause merge conflicts and unnecessary diff noise.

Add .dart_tool/ to your .gitignore and remove these files from the repository:

# Add to .gitignore
echo ".dart_tool/" >> .gitignore

# Remove from git
git rm -r examples/journalist_agent/dart_sdk/.dart_tool/
🤖 Prompt for AI Agents
In examples/journalist_agent/dart_sdk/.dart_tool/package_graph.json (lines
1-124): this file lives under the generated .dart_tool/ directory which should
not be versioned; update the repo by adding ".dart_tool/" to the repository
.gitignore, remove the examples/journalist_agent/dart_sdk/.dart_tool/ directory
from git tracking (so it is no longer committed), and commit the changes so
future runs of dart tooling regenerate those files locally without causing diffs
or merge conflicts.

Comment on lines +8 to +10
dependencies:
runagent:
path: /home/azureuser/runagent/runagent-dart No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Replace absolute path with relative path for portability.

The runagent dependency uses a hardcoded absolute path /home/azureuser/runagent/runagent-dart that is specific to one development environment. This prevents the project from working on other systems.

Apply this diff to use a relative path from the project root:

 dependencies:
   runagent:
-    path: /home/azureuser/runagent/runagent-dart
+    path: ../../../runagent-dart

Or, if this is intended for published use, reference the pub.dev package:

 dependencies:
-  runagent:
-    path: /home/azureuser/runagent/runagent-dart
+  runagent: ^0.1.41
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
dependencies:
runagent:
path: /home/azureuser/runagent/runagent-dart
dependencies:
runagent:
path: ../../../runagent-dart
Suggested change
dependencies:
runagent:
path: /home/azureuser/runagent/runagent-dart
dependencies:
runagent: ^0.1.41
🤖 Prompt for AI Agents
In examples/journalist_agent/dart_sdk/pubspec.yaml around lines 8 to 10, the
runagent dependency uses an absolute path
(/home/azureuser/runagent/runagent-dart) which breaks portability; change it to
a relative path from the project root (e.g., path: ../../runagent/runagent-dart
or the correct relative location within the repo) or, if this package is
intended to be published/consumed from pub.dev, replace the path dependency with
the published package name and version. Ensure the chosen path resolves
correctly from the pubspec.yaml location and update any .gitignore or repo
layout if needed.

Comment on lines +28 to +41
After deployment, you'll get an `agent_id`. Update this in:
- `backend/app.py` (both client instances)
- `test_dart/lib/main.dart`

### 2.1 Local vs Cloud Runs

- **Local:** Keep the `local` flag in `test_dart/lib/main.dart` (or your Dart sample) and make sure `host`/`port` point to your `runagent serve` process (defaults: `127.0.0.1:8451`).
- **Cloud:** Comment out the `local` override, then authenticate once per shell:

```bash
export RUNAGENT_API_KEY="your-runagent-api-key"
```

Use the cloud agent ID returned from the dashboard when you deploy remotely.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Clarify agent_id acquisition and local vs cloud configuration.

The instructions reference updating the agent_id in multiple files but don't clearly explain:

  • Where/how to find the agent_id from runagent serve output
  • What the local flag does and how it's implemented in the Dart code
  • Whether the default host 127.0.0.1:8451 matches the RunAgent local server defaults

Consider adding explicit pointers or example agent_id values, and briefly document how the local flag overrides configuration.


🏁 Script executed:

#!/bin/bash
# Find Dart SDK implementation files
fd -e dart -p 'dart.*sdk|sdk.*dart' --type f | head -20

Length of output: 48


🏁 Script executed:

#!/bin/bash
# Search for Dart client implementation with run/runStream methods
rg -n "runStream|\.run\(" --type dart -C 3 | head -50

Length of output: 3376


🏁 Script executed:

#!/bin/bash
# Find backend app.py and search for API endpoints
fd -e py 'backend.*app|app.*backend' --type f | head -10

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Search for /api/article endpoints in Python files
rg -n "api/article|api.*article" --type py -C 2 | head -50

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Find test_dart directory and main.dart file
fd 'test_dart' --type d

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Search for configuration with host and port 8451
rg -n "8451|127.0.0.1.*8451" -C 2 | head -50

Length of output: 2871


🏁 Script executed:

#!/bin/bash
# Look for runagent configuration or defaults
rg -n "local.*flag|host.*port.*default" --type dart --type py -C 2 | head -50

Length of output: 1782


🏁 Script executed:

#!/bin/bash
# List all files in examples/journalist_agent/ to see actual structure
fd . examples/journalist_agent/ --type f | head -30

Length of output: 283


🏁 Script executed:

#!/bin/bash
# Search for Python files in examples/journalist_agent/
fd -e py examples/journalist_agent/ --type f

Length of output: 409


🏁 Script executed:

#!/bin/bash
# Search for Dart files in examples/journalist_agent/ (excluding dart_sdk/Readme.md)
fd -e dart examples/journalist_agent/ --type f

Length of output: 409


🏁 Script executed:

#!/bin/bash
# Search for any backend or app files in examples/ directory
fd -e py examples/ --type f | grep -E "app|backend|server" | head -20

Length of output: 341


🏁 Script executed:

#!/bin/bash
# Look for /api/ or article references in all Python files in examples/
rg -n "api.*article|article.*api" --type py examples/ -C 2

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Check runagent-dart client implementation for run() method signature
rg -n "Future.*run\(" --type dart runagent-dart/lib/src/ -C 3 | head -40

Length of output: 544


🏁 Script executed:

#!/bin/bash
# Read the actual backend agent file
cat examples/journalist_agent/agent/main.py

Length of output: 2587


🏁 Script executed:

#!/bin/bash
# Read the actual Dart example file
cat examples/journalist_agent/dart_sdk/lib/main.dart

Length of output: 993


🏁 Script executed:

#!/bin/bash
# Read the config file
cat examples/journalist_agent/agent/runagent.config.json

Length of output: 799


🏁 Script executed:

#!/bin/bash
# Search for any Flask/FastAPI route decorators and endpoints
rg -n "@app\.|@.*route|@.*post|@.*get" --type py examples/journalist_agent/ -A 2

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Search for any article-related code in agent files
rg -n "article" --type py -i examples/journalist_agent/

Length of output: 1115


Update file path references to match actual codebase locations.

The README contains incorrect file path references that will prevent developers from following the instructions:

  • backend/app.py → should be agent/main.py (though note that agent/main.py is the agent definition itself, not a client application—there are no "client instances" to update there)
  • test_dart/lib/main.dart → should be dart_sdk/lib/main.dart

The correct location for updating the agent_id is in examples/journalist_agent/dart_sdk/lib/main.dart (the hardcoded agentId: '9fac4988-d88e-4d6c-994c-7495c11de8b9'). The reference to updating client instances in backend/app.py does not apply to the actual codebase structure, since agent/main.py contains the agent definition, not client code. Clarify or remove the backend reference to avoid confusion.

Comment on lines +1 to +452
{
"roots": [
"runagent"
],
"packages": [
{
"name": "runagent",
"version": "0.1.41",
"dependencies": [
"http",
"web_socket_channel"
],
"devDependencies": [
"lints",
"test"
]
},
{
"name": "lints",
"version": "3.0.0",
"dependencies": []
},
{
"name": "test",
"version": "1.28.0",
"dependencies": [
"analyzer",
"async",
"boolean_selector",
"collection",
"coverage",
"http_multi_server",
"io",
"matcher",
"node_preamble",
"package_config",
"path",
"pool",
"shelf",
"shelf_packages_handler",
"shelf_static",
"shelf_web_socket",
"source_span",
"stack_trace",
"stream_channel",
"test_api",
"test_core",
"typed_data",
"web_socket_channel",
"webkit_inspection_protocol",
"yaml"
]
},
{
"name": "web_socket_channel",
"version": "2.4.5",
"dependencies": [
"async",
"crypto",
"stream_channel",
"web"
]
},
{
"name": "http",
"version": "1.6.0",
"dependencies": [
"async",
"http_parser",
"meta",
"web"
]
},
{
"name": "yaml",
"version": "3.1.3",
"dependencies": [
"collection",
"source_span",
"string_scanner"
]
},
{
"name": "webkit_inspection_protocol",
"version": "1.2.1",
"dependencies": [
"logging"
]
},
{
"name": "typed_data",
"version": "1.4.0",
"dependencies": [
"collection"
]
},
{
"name": "test_core",
"version": "0.6.14",
"dependencies": [
"analyzer",
"args",
"async",
"boolean_selector",
"collection",
"coverage",
"frontend_server_client",
"glob",
"io",
"meta",
"package_config",
"path",
"pool",
"source_map_stack_trace",
"source_maps",
"source_span",
"stack_trace",
"stream_channel",
"test_api",
"vm_service",
"yaml"
]
},
{
"name": "test_api",
"version": "0.7.8",
"dependencies": [
"async",
"boolean_selector",
"collection",
"meta",
"source_span",
"stack_trace",
"stream_channel",
"string_scanner",
"term_glyph"
]
},
{
"name": "stream_channel",
"version": "2.1.4",
"dependencies": [
"async"
]
},
{
"name": "stack_trace",
"version": "1.12.1",
"dependencies": [
"path"
]
},
{
"name": "source_span",
"version": "1.10.1",
"dependencies": [
"collection",
"path",
"term_glyph"
]
},
{
"name": "shelf_web_socket",
"version": "3.0.0",
"dependencies": [
"shelf",
"stream_channel",
"web_socket_channel"
]
},
{
"name": "shelf_static",
"version": "1.1.3",
"dependencies": [
"convert",
"http_parser",
"mime",
"path",
"shelf"
]
},
{
"name": "shelf_packages_handler",
"version": "3.0.2",
"dependencies": [
"path",
"shelf",
"shelf_static"
]
},
{
"name": "shelf",
"version": "1.4.2",
"dependencies": [
"async",
"collection",
"http_parser",
"path",
"stack_trace",
"stream_channel"
]
},
{
"name": "pool",
"version": "1.5.2",
"dependencies": [
"async",
"stack_trace"
]
},
{
"name": "path",
"version": "1.9.1",
"dependencies": []
},
{
"name": "package_config",
"version": "2.2.0",
"dependencies": [
"path"
]
},
{
"name": "node_preamble",
"version": "2.0.2",
"dependencies": []
},
{
"name": "matcher",
"version": "0.12.18",
"dependencies": [
"async",
"meta",
"stack_trace",
"term_glyph",
"test_api"
]
},
{
"name": "io",
"version": "1.0.5",
"dependencies": [
"meta",
"path",
"string_scanner"
]
},
{
"name": "http_multi_server",
"version": "3.2.2",
"dependencies": [
"async"
]
},
{
"name": "coverage",
"version": "1.15.0",
"dependencies": [
"args",
"cli_config",
"glob",
"logging",
"meta",
"package_config",
"path",
"source_maps",
"stack_trace",
"vm_service",
"yaml"
]
},
{
"name": "collection",
"version": "1.19.1",
"dependencies": []
},
{
"name": "boolean_selector",
"version": "2.1.2",
"dependencies": [
"source_span",
"string_scanner"
]
},
{
"name": "async",
"version": "2.13.0",
"dependencies": [
"collection",
"meta"
]
},
{
"name": "analyzer",
"version": "9.0.0",
"dependencies": [
"_fe_analyzer_shared",
"collection",
"convert",
"crypto",
"glob",
"meta",
"package_config",
"path",
"pub_semver",
"source_span",
"watcher",
"yaml"
]
},
{
"name": "web",
"version": "0.5.1",
"dependencies": []
},
{
"name": "crypto",
"version": "3.0.7",
"dependencies": [
"typed_data"
]
},
{
"name": "meta",
"version": "1.17.0",
"dependencies": []
},
{
"name": "http_parser",
"version": "4.1.2",
"dependencies": [
"collection",
"source_span",
"string_scanner",
"typed_data"
]
},
{
"name": "string_scanner",
"version": "1.4.1",
"dependencies": [
"source_span"
]
},
{
"name": "logging",
"version": "1.3.0",
"dependencies": []
},
{
"name": "vm_service",
"version": "15.0.2",
"dependencies": []
},
{
"name": "source_maps",
"version": "0.10.13",
"dependencies": [
"source_span"
]
},
{
"name": "source_map_stack_trace",
"version": "2.1.2",
"dependencies": [
"path",
"source_maps",
"stack_trace"
]
},
{
"name": "glob",
"version": "2.1.3",
"dependencies": [
"async",
"collection",
"file",
"path",
"string_scanner"
]
},
{
"name": "frontend_server_client",
"version": "4.0.0",
"dependencies": [
"async",
"path"
]
},
{
"name": "args",
"version": "2.7.0",
"dependencies": []
},
{
"name": "term_glyph",
"version": "1.2.2",
"dependencies": []
},
{
"name": "mime",
"version": "2.0.0",
"dependencies": []
},
{
"name": "convert",
"version": "3.1.2",
"dependencies": [
"typed_data"
]
},
{
"name": "cli_config",
"version": "0.2.0",
"dependencies": [
"args",
"yaml"
]
},
{
"name": "watcher",
"version": "1.1.4",
"dependencies": [
"async",
"path"
]
},
{
"name": "pub_semver",
"version": "2.2.0",
"dependencies": [
"collection"
]
},
{
"name": "_fe_analyzer_shared",
"version": "92.0.0",
"dependencies": [
"meta"
]
},
{
"name": "file",
"version": "7.0.1",
"dependencies": [
"meta",
"path"
]
}
],
"configVersion": 1
} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove generated .dart_tool files from version control.

The .dart_tool/ directory contains auto-generated files that should not be committed to version control. These files are regenerated by Dart's pub tool on each machine and can cause merge conflicts. Add .dart_tool/ to your .gitignore file.

Apply this change to your .gitignore:

+# Dart tool files
+.dart_tool/
+.packages

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In runagent-dart/.dart_tool/package_graph.json lines 1-452: the committed
.dart_tool directory is generated and should be removed from version control;
update .gitignore to add a line ".dart_tool/" (or ".dart_tool" ), then remove
the tracked files and directory from git (e.g. git rm -r --cached .dart_tool &&
git commit -m "Remove generated .dart_tool files and add to .gitignore") so the
folder remains local and untracked on future commits.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.41] - 2024-XX-XX
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Update placeholder date before release.

The release date is set to 2024-XX-XX as a placeholder. Ensure this is updated to the actual release date before publishing to pub.dev.

-## [0.1.41] - 2024-XX-XX
+## [0.1.41] - 2025-XX-XX

Note: The year should be 2025 based on the PR creation date (2025-11-24 from PR objectives).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## [0.1.41] - 2024-XX-XX
## [0.1.41] - 2025-XX-XX
🤖 Prompt for AI Agents
In runagent-dart/CHANGELOG.md around line 8, the release entry uses a
placeholder date "2024-XX-XX"; update this to the actual release date (replace
"2024-XX-XX" with the real YYYY-MM-DD) and make sure the year is 2025 per the PR
creation date; commit the updated CHANGELOG.md with the correct ISO-style date
for the release.

Comment on lines +80 to +93
factory AgentArchitecture.fromJson(Map<String, dynamic> json) {
final agentIdValue = json['agent_id'] ?? json['agentId'];
final entrypointsValue = json['entrypoints'];

return AgentArchitecture(
agentId: agentIdValue is String ? agentIdValue : (agentIdValue?.toString() ?? ''),
entrypoints: entrypointsValue is List
? entrypointsValue
.whereType<Map<String, dynamic>>()
.map((e) => EntryPoint.fromJson(e))
.toList()
: [],
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Consider validation for required agentId field.

The fromJson method tolerantly converts missing or invalid agentId values to an empty string (line 85). While this defensive parsing prevents exceptions, it allows invalid AgentArchitecture objects to be created with an empty required field. Consider whether validation should be stricter here.

If agentId is truly required, consider throwing an exception for missing/invalid values:

   factory AgentArchitecture.fromJson(Map<String, dynamic> json) {
     final agentIdValue = json['agent_id'] ?? json['agentId'];
     final entrypointsValue = json['entrypoints'];
+    
+    if (agentIdValue == null || agentIdValue.toString().isEmpty) {
+      throw FormatException('agentId is required in AgentArchitecture');
+    }
     
     return AgentArchitecture(
       agentId: agentIdValue is String ? agentIdValue : (agentIdValue?.toString() ?? ''),
       entrypoints: entrypointsValue is List
           ? entrypointsValue
               .whereType<Map<String, dynamic>>()
               .map((e) => EntryPoint.fromJson(e))
               .toList()
           : [],
     );
   }

Alternatively, if silent fallback is intentional (e.g., for partial data scenarios), add a comment explaining the design decision.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
factory AgentArchitecture.fromJson(Map<String, dynamic> json) {
final agentIdValue = json['agent_id'] ?? json['agentId'];
final entrypointsValue = json['entrypoints'];
return AgentArchitecture(
agentId: agentIdValue is String ? agentIdValue : (agentIdValue?.toString() ?? ''),
entrypoints: entrypointsValue is List
? entrypointsValue
.whereType<Map<String, dynamic>>()
.map((e) => EntryPoint.fromJson(e))
.toList()
: [],
);
}
factory AgentArchitecture.fromJson(Map<String, dynamic> json) {
final agentIdValue = json['agent_id'] ?? json['agentId'];
final entrypointsValue = json['entrypoints'];
if (agentIdValue == null || agentIdValue.toString().isEmpty) {
throw FormatException('agentId is required in AgentArchitecture');
}
return AgentArchitecture(
agentId: agentIdValue is String ? agentIdValue : (agentIdValue?.toString() ?? ''),
entrypoints: entrypointsValue is List
? entrypointsValue
.whereType<Map<String, dynamic>>()
.map((e) => EntryPoint.fromJson(e))
.toList()
: [],
);
}
🤖 Prompt for AI Agents
In runagent-dart/lib/src/types/types.dart around lines 80 to 93, the factory
currently converts a missing or invalid agentId to an empty string which permits
creating invalid AgentArchitecture instances; update the factory to validate
agentId: read agentIdValue (from 'agent_id' or 'agentId'), convert to String if
present, then if the resulting string is null or empty throw a descriptive
FormatException (or ArgumentError) indicating agentId is required; if the
project intentionally allows empty agentId, instead add a clear comment above
the factory describing that silent fallback behavior and why it is acceptable.

Comment on lines +112 to +121
factory EntryPoint.fromJson(Map<String, dynamic> json) {
final tagValue = json['tag'];
return EntryPoint(
tag: tagValue is String ? tagValue : (tagValue?.toString() ?? ''),
file: json['file'] is String ? json['file'] : null,
module: json['module'] is String ? json['module'] : null,
extractor: json['extractor'] is String ? json['extractor'] : null,
description: json['description'] is String ? json['description'] : null,
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Consider validation for required tag field.

Similar to AgentArchitecture, the fromJson method converts missing or invalid tag values to an empty string (line 115). This allows invalid EntryPoint objects with empty required fields.

Consider adding validation:

   factory EntryPoint.fromJson(Map<String, dynamic> json) {
     final tagValue = json['tag'];
+    
+    if (tagValue == null || tagValue.toString().isEmpty) {
+      throw FormatException('tag is required in EntryPoint');
+    }
+    
     return EntryPoint(
       tag: tagValue is String ? tagValue : (tagValue?.toString() ?? ''),
       file: json['file'] is String ? json['file'] : null,
       module: json['module'] is String ? json['module'] : null,
       extractor: json['extractor'] is String ? json['extractor'] : null,
       description: json['description'] is String ? json['description'] : null,
     );
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
factory EntryPoint.fromJson(Map<String, dynamic> json) {
final tagValue = json['tag'];
return EntryPoint(
tag: tagValue is String ? tagValue : (tagValue?.toString() ?? ''),
file: json['file'] is String ? json['file'] : null,
module: json['module'] is String ? json['module'] : null,
extractor: json['extractor'] is String ? json['extractor'] : null,
description: json['description'] is String ? json['description'] : null,
);
}
factory EntryPoint.fromJson(Map<String, dynamic> json) {
final tagValue = json['tag'];
if (tagValue == null || tagValue.toString().isEmpty) {
throw FormatException('tag is required in EntryPoint');
}
return EntryPoint(
tag: tagValue is String ? tagValue : (tagValue?.toString() ?? ''),
file: json['file'] is String ? json['file'] : null,
module: json['module'] is String ? json['module'] : null,
extractor: json['extractor'] is String ? json['extractor'] : null,
description: json['description'] is String ? json['description'] : null,
);
}
🤖 Prompt for AI Agents
In runagent-dart/lib/src/types/types.dart around lines 112 to 121, the
EntryPoint.fromJson factory silently converts a missing or invalid tag into an
empty string which allows construction of invalid EntryPoint instances; change
the method to validate that json['tag'] exists and is a non-empty String and if
not throw a FormatException (or return null/throw) instead of coercing to '',
and keep other optional fields as-is—this ensures required tag is enforced and
invalid input fails fast.

Comment on lines +1 to +106
{
"configVersion": 2,
"packages": [
{
"name": "async",
"rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/async-2.13.0",
"packageUri": "lib/",
"languageVersion": "3.4"
},
{
"name": "collection",
"rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/collection-1.19.1",
"packageUri": "lib/",
"languageVersion": "3.4"
},
{
"name": "crypto",
"rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/crypto-3.0.7",
"packageUri": "lib/",
"languageVersion": "3.4"
},
{
"name": "http",
"rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/http-1.6.0",
"packageUri": "lib/",
"languageVersion": "3.4"
},
{
"name": "http_parser",
"rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/http_parser-4.1.2",
"packageUri": "lib/",
"languageVersion": "3.4"
},
{
"name": "meta",
"rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/meta-1.17.0",
"packageUri": "lib/",
"languageVersion": "3.5"
},
{
"name": "path",
"rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/path-1.9.1",
"packageUri": "lib/",
"languageVersion": "3.4"
},
{
"name": "runagent",
"rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/runagent-0.1.41",
"packageUri": "lib/",
"languageVersion": "3.0"
},
{
"name": "source_span",
"rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/source_span-1.10.1",
"packageUri": "lib/",
"languageVersion": "3.1"
},
{
"name": "stream_channel",
"rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/stream_channel-2.1.4",
"packageUri": "lib/",
"languageVersion": "3.3"
},
{
"name": "string_scanner",
"rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/string_scanner-1.4.1",
"packageUri": "lib/",
"languageVersion": "3.1"
},
{
"name": "term_glyph",
"rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/term_glyph-1.2.2",
"packageUri": "lib/",
"languageVersion": "3.1"
},
{
"name": "typed_data",
"rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/typed_data-1.4.0",
"packageUri": "lib/",
"languageVersion": "3.5"
},
{
"name": "web",
"rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/web-0.5.1",
"packageUri": "lib/",
"languageVersion": "3.3"
},
{
"name": "web_socket_channel",
"rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/web_socket_channel-2.4.5",
"packageUri": "lib/",
"languageVersion": "3.3"
},
{
"name": "test_agno",
"rootUri": "../",
"packageUri": "lib/",
"languageVersion": "3.0"
}
],
"generator": "pub",
"generatorVersion": "3.10.0",
"flutterRoot": "file:///home/azureuser/snap/flutter/common/flutter",
"flutterVersion": "3.38.2",
"pubCache": "file:///home/azureuser/.pub-cache"
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove generated configuration file with absolute paths.

This file contains machine-specific absolute paths (e.g., /home/azureuser/.pub-cache) that will not work on other machines. As a generated file in the .dart_tool/ directory, it should not be committed to version control.

Ensure .dart_tool/ is in your .gitignore to prevent committing generated files:

+# Dart tool files
+.dart_tool/
+.packages

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In test_scripts/dart/test_agno/.dart_tool/package_config.json lines 1-106: this
is a generated file containing machine-specific absolute paths and must not be
committed; remove the file from the repository, add .dart_tool/ to .gitignore
(or ensure it is present), commit the .gitignore change, and then delete the
tracked package_config.json from git (git rm --cached or equivalent) so it is no
longer versioned; developers can recreate it locally by running pub get/flutter
pub get when needed.

@sawradip sawradip merged commit aab9f2b into main Nov 24, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants