Skip to content

AI Agents & LLM Operators ​

BLOGE treats LLM-driven orchestration as a first-class concern. The bloge-agent-ext module ships an agent DSL and runtime, bloge-common-operators exposes an extended LlmProvider SPI and a conversation-memory operator, and the graph-engine project adds an AI authoring pipeline that generates .bloge DSL from natural language.

The agent loop ​

An agent is a reasoning loop around an LlmProvider. It calls the model, optionally invokes the tools you declared, feeds observations back into memory, and repeats until an exit condition is met.

bloge
agent customerSupport {
  model                = "gpt-6-astra"
  system_prompt        = "You are a helpful customer support agent."
  max_turns            = 6
  max_tool_concurrency = 2
  temperature          = 0.2
  memory               = sliding_window(20)

  tool searchKnowledgeBase : KBSearchOperator {
    description = "Search the knowledge base for a relevant article"
    input { query = tool_args.query }
  }

  tool createTicket : CreateTicketOperator {
    description = "Create a support ticket for follow-up"
    input {
      title       = tool_args.title
      description = tool_args.description
      priority    = tool_args.priority
    }
  }

  exit_condition = finish_reason == "stop" || tool_call("escalateToHuman")
}
  • tool_args.<field> is only meaningful inside a tool input { ... } block. The compiler normalizes those references into context paths and infers the JSON tool schema sent to the model.
  • max_tool_concurrency caps how many declared tools may execute in parallel during one reasoning turn; omit it for unlimited fan-out.
  • exit_condition ends the loop — on a natural finish_reason, a specific tool_call(...), or any expression over context.

Streaming agents ​

For chunked output, use either stream agent ... or streaming = true; the runtime swaps in the StreamingAgentLoopOperator around llmStreamingChat.

Memory strategies ​

Memory controls what conversation history the model sees each turn:

StrategyBehavior
fullKeep the entire history
sliding_window(n)Keep the most recent n messages
token_budget(n)Keep as much recent history as fits in a token budget
summarySummarize older turns to stay compact

bloge-common-operators also ships a standalone conversation operator with full, sliding_window, and token_budget strategies plus an optional TokenEstimator SPI for precise token counting.

The Java builder ​

Agents can be built without the DSL via AgentBuilder:

java
AgentLoopOperator agent = AgentBuilder.create("customerSupport")
    .model("gpt-6-astra")
    .systemPrompt("You are a helpful customer support agent.")
    .maxTurns(6)
    .maxToolConcurrency(2)
    .temperature(0.2)
    .memory(new AgentMemoryStrategy.SlidingWindow(20))
    .tool(new AgentToolRef(
        "searchKnowledgeBase",
        "KBSearchOperator",
        "Search the knowledge base for a relevant article",
        searchToolGraph,
        "searchKnowledgeBase",
        null))
    .exitCondition("finish_reason == \"stop\"")
    .toOperator("CustomerSupportAgent", registry);

Use toBuilder() on a compiled AgentDef to derive variants, or compile a top-level agent document with AgentDslCompiler.

Extended LlmProvider SPI ​

bloge-common-operators extends the provider contract while keeping the original text-only convenience constructors for backward compatibility:

  • Tool calling — ToolDefinition, ToolCall.
  • Structured output — ResponseFormat.Text, JsonObject, JsonSchema.
  • Multimodal — LlmProvider.ContentPart message parts.

The original LlmMessage(role, content) and LlmRequest(model, messages) constructors still work.

Dynamic sub-graphs ​

The dynamicSubGraph operator sandbox-validates runtime-generated BLOGE DSL via DslSandbox + DslSandboxPolicy, compiles it with the current operator registry, and runs it as a nested sub-graph. This enables graph-factory patterns where an upstream node — say, an LLM — emits a small workflow that executes immediately.

AI authoring pipeline ​

The standalone graph-engine ai module (bloge-graph-engine-ai) assembles syntax-reference and operator-catalog prompt context, calls an LlmProvider to generate .bloge DSL from natural language, and validates each candidate through a parse → lint → compile pipeline backed by bloge-lint quality scoring, with up to two structured repair retries. The control-plane server exposes it as draft-only /api/v1/ai/validate and /api/v1/ai/generate endpoints that persist nothing.

Next steps ​