DEV Community

Solon Framework
Solon Framework

Posted on

Solon AI Talents: Building Modular, Context-Aware AI Agents Beyond Simple Tools

Solon AI Talents: Building Modular, Context-Aware AI Agents Beyond Simple Tools

If you've built AI agents before, you've probably hit this wall: your tool list grows too long, the model gets confused about when to use what, and your code turns into a tangled mess of if-else branching just to decide which tools to expose.

I've been there. And after spending some time with Solon's AI framework, I found something that changed how I think about agent architecture: Talents.

The Problem with Plain Tool Orchestration

Let's say you're building an internal support agent. It needs to:

  • Search the knowledge base
  • Check order status
  • Reset user passwords
  • Escalate to admin (for admins only)
  • Access billing info (for finance team only)

With plain tools, you'd typically do:

model.prompt("I need to reset my password").options(o->{o.toolAdd(newKbSearchTool());o.toolAdd(newOrderStatusTool());o.toolAdd(newPasswordResetTool());if("admin".equals(role)){o.toolAdd(newAdminEscalationTool());}if("finance".equals(role)){o.toolAdd(newBillingTool());}}).call();
Enter fullscreen modeExit fullscreen mode

This works, but it's fragile. The business logic is scattered across call sites. The model sees 5+ tools even when the user just wants to reset a password. And when you have 20+ tools, the model's reasoning quality drops noticeably.

What Are Talents?

Solon Talents are self-contained capability modules — think of them as mini-agents within your agent. Each Talent bundles three things:

  1. Awareness (isSupported) — Can I handle this request?
  2. Instruction (getInstruction) — What SOP should the model follow when using me?
  3. Execution (getTools) — What tools do I expose?

When you register Talents, the framework automatically:

  • Filters inactive Talents based on user intent (saves tokens)
  • Injects only relevant instructions into the System Message
  • "Colors" each tool with its Talent's metadata — so the model knows exactly which SOP applies to which tool

Defining a Talent

There are two ways to build a Talent. I'll show both.

Way 1: Declarative with TalentDesc (Quick & Dynamic)

When you need something fast and don't want to create a new class:

TalentDescorderExpert=newTalentDesc("order_expert").description("Order management assistant")// Only activate when user mentions orders.isSupported(prompt->prompt.getUserContent().contains("order"))// Dynamic instruction based on user level.instruction(prompt->{if("VIP".equals(prompt.attr("user_level"))){return"This is a VIP customer. Prioritize fast-track processing.";}return"Process orders using standard procedures.";}).toolAdd(newOrderQueryTool()).toolAdd(newOrderCancelTool());
Enter fullscreen modeExit fullscreen mode

Then register it:

ChatModelmodel=ChatModel.of(config).defaultTalentAdd(orderExpert).build();
Enter fullscreen modeExit fullscreen mode

Way 2: OOP with AbsTalent (For Complex Logic)

When you need dependency injection, state management, or complex business logic:

@ComponentpublicclassTechSupportTalentextendsAbsTalent{@InjectprivateKbServicekbService;@OverridepublicStringname(){return"tech_support";}@OverridepublicStringdescription(){return"Technical support specialist — handles troubleshooting and config resets";}@OverridepublicbooleanisSupported(Promptprompt){Stringcontent=prompt.getUserContent();returncontent!=null&&(content.contains("error")||content.contains("bug")||content.contains("故障"));}@OverridepublicStringgetInstruction(Promptprompt){return"""
You are a technical support specialist. Follow these SOPs:
1. First search the knowledge base for known solutions
2. Verify the user's Solon version before suggesting fixes
3. If modifying production config, clearly state the risks
""";}@ToolMapping(name="search_kb",description="Search the knowledge base for solutions")publicStringsearchKb(@Param("query")Stringquery){returnkbService.search(query);}@ToolMapping(name="reset_config",description="Reset system configuration (high-risk operation)",meta="{'danger': true, 'confirm_msg': 'Service will restart. Proceed?'}")publicStringresetConfig(@Param("serviceName")StringserviceName){return"Service ["+serviceName+"] config reset, restarting...";}}
Enter fullscreen modeExit fullscreen mode

Dynamic Context Injection with Prompt Attrs

This is where Talents really shine. The Prompt object carries runtime attributes — invisible to the LLM, but accessible to your Talent logic.

// Build a prompt with business contextPromptprompt=Prompt.of("I need to check order #12345").attrPut("tenant_id","tenant_abc").attrPut("user_role","ADMIN").attrPut("user_level","VIP");model.prompt(prompt).call();
Enter fullscreen modeExit fullscreen mode

Inside your Talent, you can access these:

publicclassOrderManagerTalentimplementsTalent{@OverridepublicbooleanisSupported(Promptprompt){// Only activate if we have a valid tenant contextreturnprompt.attr("tenant_id")!=null&&prompt.getUserContent().contains("order");}@OverridepublicStringgetInstruction(Promptprompt){Stringtenant=prompt.attrOrDefault("tenant_name","unknown");return"You are the order manager for ["+tenant+"]. Only handle this tenant's data.";}@OverridepublicCollection<FunctionTool>getTools(Promptprompt){List<FunctionTool>tools=newArrayList<>();tools.add(newOrderQueryTool());// Only admins get the cancel toolif("ADMIN".equals(prompt.attr("user_role"))){tools.add(newOrderCancelTool());}returntools;}}
Enter fullscreen modeExit fullscreen mode

Registering Talents — Global vs Per-Request

Global registration (for always-on capabilities)

ChatModelmodel=ChatModel.of(config).defaultTalentAdd(securityAuditTalent)// always active.defaultTalentAdd(0,translationTalent)// with priority (index).build();
Enter fullscreen modeExit fullscreen mode

Per-request injection (for dynamic scenarios)

model.prompt("What's the weather in Tokyo?").options(o->{o.talentAdd(weatherTalent);o.talentAdd(2,languageTalent);// with priority}).call();
Enter fullscreen modeExit fullscreen mode

Priority matters

Talents are processed in registration order. Instructions are accumulated into the System Message sequentially. The framework "colors" each tool with its Talent's identity, so the model associates the right SOP with the right tool set.

When to Use Talents vs Plain Tools

ScenarioUse ToolsUse Talents
Simple stateless function
Needs SOP instructions
Dynamic activation by context
Permission-based tool filtering
Single-purpose utility
Multi-tool coordination

Rule of thumb: If your tool needs more than a description to explain when and how to use it, wrap it in a Talent.

Putting It All Together: A Multi-Tenant Support Agent

Here's a complete example showing how Talents make multi-tenant support clean:

@ComponentpublicclassTenantAwareSupportAgent{@InjectprivateTenantServicetenantService;privatefinalChatModelmodel;publicTenantAwareSupportAgent(){this.model=ChatModel.of(config).defaultTalentAdd(newOrderManagerTalent()).defaultTalentAdd(newTechSupportTalent()).defaultTalentAdd(newBillingTalent()).build();}publicStringhandle(StringuserMessage,StringtenantId,Stringrole){// Load tenant contextTenanttenant=tenantService.findById(tenantId);Promptprompt=Prompt.of(userMessage).attrPut("tenant_id",tenant.id()).attrPut("tenant_name",tenant.name()).attrPut("user_role",role);ChatResponseresp=model.prompt(prompt).call();returnresp.getMessage();}}
Enter fullscreen modeExit fullscreen mode

The calling code is clean. The Talent logic is self-contained. And the model only sees the tools relevant to the current request.

The One Thing I Wish I Knew Earlier

Talents aren't just "tools with instructions." They're decision boundaries for your AI. Each Talent draws a clear line: "I handle this domain, and here's exactly how." The model doesn't have to guess which tool to use — the Talent's SOP guides it precisely.

This is especially noticeable when you have 10+ tools. Before Talents, the model would occasionally call the wrong tool or try to use a tool outside its intended context. After moving to Talents with isSupported guards, those issues largely disappeared.

Next Steps

The Solon AI docs have more depth on:

If you're building production AI agents with Solon, Talents are the architecture pattern you didn't know you needed. Try wrapping your next tool set into a Talent — the difference in model behavior is immediate.

Top comments (0)