Class AgentBuilder
This builder provides a fluent API for constructing agents with custom configurations, ideal for:
- Testing with mock dependencies
- Creating agents programmatically at runtime
- Dynamic agent configuration from external sources
Example usage:
// Simple agent with LLM and role
Agent agent = AgentBuilder.create()
.id("support-agent")
.llm(new GeminiClient("gemini-2.0-flash"))
.role(new CustomerSupportRole())
.build();
// Full configuration
Agent agent = AgentBuilder.create()
.id("research-agent")
.llm(llmClient)
.memoryStore(new FileMemoryStore("./memory"))
.roles(List.of(researchRole, analysisRole))
.communication(Communication.formal())
.maxContextTokens(8000)
.build();
// Testing with mocks
Agent testAgent = AgentBuilder.create()
.id("test-agent")
.llm(mockLLM)
.memoryStore(mockMemory)
.actionExecutor(mockExecutor)
.build(); // McpClient de builder'a eklenmeli
- See Also:
-
Method Summary
Modifier and TypeMethodDescriptionactionExecutor(ActionExecutor actionExecutor) Sets the action executor for tool execution.actionKnowledge(String action, String... entryNames) Names the knowledge one action uses, replacing the list its@ActionSpecnames.authorityScope(AuthorityScope scope) Pre-declared authority bounds recorded on every dispatch (TNS-298).autoStart(boolean autoStart) Sets whether the agent auto-starts its protocols — programmatic parity forAgentSpec.autoStart()(TNS-534).build()Builds and returns the configured Agent instance.builtInTools(BuiltInTool... tools) Adds one or more shippedtoolkits to the agent.invalid reference
BuiltInToolcommunication(Communication communication) Sets the communication style for the agent.static AgentBuildercreate()Creates a new AgentBuilder instance.description(String description) Sets the agent's human-readable description — programmatic parity forAgentSpec.description()(TNS-534).Sets the agent's decentralized identity configuration — programmatic parity forAgentSpec.did()(TNS-534).dynamicTool(DynamicToolMethod dynamicTool) Adds aDynamicToolMethod— a tool whose name, description, schema, and dispatch handler are all supplied at construction time.dynamicTools(List<DynamicToolMethod> dynamicTools) Adds a batch ofDynamicToolMethods.errorRecoveryScenario(ErrorRecoveryScenario scenario) Adds an error recovery scenario to the agent.errorRecoveryScenarios(List<ErrorRecoveryScenario> scenarios) Adds multiple error recovery scenarios to the agent.groupMembership(GroupMemberSpec groupMembership) Sets the agent's group membership configuration — programmatic parity forAgentSpec.groups()(TNS-534).Sets the agent ID.idempotencyStore(IdempotencyStore store) Sets theIdempotencyStoreconsulted for tools guarded by@Idempotent.identities(List<AgentIdentity> identities) Adds multiple identities to the agent.identity(AgentIdentity identity) Adds an identity to the agent.idleTimeoutMs(int idleTimeoutMs) Sets the idle timeout before the agent may suspend — programmatic parity forAgentSpec.idleTimeoutMs()(TNS-534).knowledge(KnowledgeEntry... entries) Gives the agent knowledge entries, layered over its@AgentSpecknowledge by name: an entry whose name the annotation declares replaces that entry (a role entry stays a role entry), and any other entry is added to the agent's chat scope.knowledgeScope(KnowledgeScope scope) Shares action-level source snapshots and ordered cursors with other agents and bridges using the same explicit knowledge scope.knowledgeUsageListener(BiConsumer<String, List<KnowledgeUsage>> listener) Receives what each knowledge source gave every chat turn (scope"chat") and every action call that runs knowledge (scope = the action name): oneKnowledgeUsagerow per source, in declaration order.liabilitySink(LiabilitySink sink) Configure theLiabilitySinkthat receives anAgentLiabilityRecordper dispatch (TNS-298).Sets the LLM client for this agent.maxActiveSkills(int limit) Cap the number of skill descriptions surfaced in the system prompt per turn (TNS-289).maxContextTokens(int maxTokens) Sets the maximum context tokens for memory pruning.memoryConfig(MemoryConfig config) Configures memory declaratively from aMemoryConfig— the programmatic equivalent of@MemorySpec(TNS-546), so a builder user gets full memory configuration without hand-building aMemoryStoreor knowing the per-store implementation classes.memoryStore(MemoryStore memoryStore) Sets the memory store for conversation history.paymentBroker(PaymentBroker broker) Plug aPaymentBrokerinto this agent (TNS-298 / TNS-449).Adds a plan to the agent.plannerHandle(PlannerHandle plannerHandle) Sets the planner handle for goal-oriented planning.Adds multiple plans to the agent.principal(AgentPrincipal principal) Attribute every action this agent dispatches toprincipal(TNS-298).promptEnhancer(PromptEnhancer enhancer) Sets a custom prompt enhancer for the agent.promptStrategies(List<PromptStrategy> strategies) Adds multiple prompt strategies to the agent.promptStrategy(PromptStrategy strategy) Adds a prompt strategy to the agent.reachabilityCheckTimeout(Duration timeout) Per-probe wall-clock budget passed to eachReachabilityValidatorwhen reachability checks are enabled.reasoningStrategy(ReasoningStrategyHandle strategy) Sets an explicit reasoning strategy handle.reasoningStrategy(String strategyName) Sets the reasoning strategy by name (e.g., "react", "tot", "got", "self-consistency").relaxValidation(String issueCode) Suppress a specificValidationIssue.code()from thebuild()pipeline.relaxValidation(Set<String> issueCodes) Bulk variant ofrelaxValidation(String)(issue #85 phase 3 acceptance bullet).Adds a role to the agent.Adds multiple roles to the agent.skillResolver(SkillResolver resolver) Override the resolver used whenskillResolverPolicyisAUTO.skillStore(SkillStore store) Wire aSkillStoreso the agent can surface on-demand modular knowledge between role and tools (TNS-289).Declares the tenant this agent is scoped to.toolCallFilter(ToolCallFilter filter) Pre-build wiring of aToolCallFilter— the runtime gate consulted before each tool invocation.Adds tools by reflecting over POJO instances bearing@Tool-annotated methods (the function-shape pattern, see RFC #188).Run the full validator pipeline against the current builder state and return the resultingValidationReport.Sets the agent version — programmatic parity forAgentSpec.version()(TNS-534).withReachabilityChecks(boolean enabled) Enable opt-in reachability probes duringbuild()(issue #85 phase 2a).
-
Method Details
-
create
Creates a new AgentBuilder instance.- Returns:
- a new builder
-
id
Sets the agent ID. If not set, a UUID will be generated.- Parameters:
id- the agent identifier- Returns:
- this builder
-
description
Sets the agent's human-readable description — programmatic parity forAgentSpec.description()(TNS-534).- Parameters:
description- agent description (surfaces in the LLM identity prompt)- Returns:
- this builder
- Since:
- 0.11.0
-
version
Sets the agent version — programmatic parity forAgentSpec.version()(TNS-534).- Parameters:
version- semantic version string (default"1.0.0")- Returns:
- this builder
- Since:
- 0.11.0
-
autoStart
Sets whether the agent auto-starts its protocols — programmatic parity forAgentSpec.autoStart()(TNS-534).- Parameters:
autoStart-trueto auto-start (annotation default)- Returns:
- this builder
- Since:
- 0.11.0
-
idleTimeoutMs
Sets the idle timeout before the agent may suspend — programmatic parity forAgentSpec.idleTimeoutMs()(TNS-534).- Parameters:
idleTimeoutMs- timeout in milliseconds (0= never suspend)- Returns:
- this builder
- Since:
- 0.11.0
-
did
Sets the agent's decentralized identity configuration — programmatic parity forAgentSpec.did()(TNS-534).- Parameters:
did- DID configuration, ornullto fall back to the annotation / default DID- Returns:
- this builder
- Since:
- 0.11.0
-
groupMembership
Sets the agent's group membership configuration — programmatic parity forAgentSpec.groups()(TNS-534).- Parameters:
groupMembership- group membership spec (seeGroupMemberSpec.of(String...))- Returns:
- this builder
- Since:
- 0.11.0
-
llm
Sets the LLM client for this agent.LLM is optional since 2.17.0. Traditional agents can operate without LLM using only LOCAL and WEB_SERVICE actions.
If not set:
- LLM actions will throw IllegalStateException
- LOCAL and WEB_SERVICE actions work normally
- Role-level LLM can still be used
- Parameters:
llmClient- the LLM client, or null for traditional agents- Returns:
- this builder
-
memoryStore
Sets the memory store for conversation history. Defaults to InMemoryStore if not set.- Parameters:
memoryStore- the memory store- Returns:
- this builder
-
memoryConfig
Configures memory declaratively from aMemoryConfig— the programmatic equivalent of@MemorySpec(TNS-546), so a builder user gets full memory configuration without hand-building aMemoryStoreor knowing the per-store implementation classes.Resolves the config into a store immediately via
MemoryStoreFactory.create(MemoryConfig)(likememoryStore(MemoryStore)), so it takes precedence over a class-level@MemorySpec. For a fully custom store implementation usememoryStore(MemoryStore)instead.AgentBuilder.create() .memoryConfig(MemoryConfig.builder() .type(MemorySpec.MemoryType.HYBRID) .capacity(200) .maxContextTokens(8000) .build()) .role(role) .build();- Parameters:
config- the memory configuration (non-null)- Returns:
- this builder
- Since:
- 0.12.0 (TNS-546)
-
actionExecutor
Sets the action executor for tool execution. Defaults to standard ActionExecutor if not set.- Parameters:
actionExecutor- the action executor- Returns:
- this builder
-
role
Adds a role to the agent.- Parameters:
role- the role to add- Returns:
- this builder
-
roles
Adds multiple roles to the agent.- Parameters:
roles- the roles to add- Returns:
- this builder
-
identity
Adds an identity to the agent.- Parameters:
identity- the identity to add- Returns:
- this builder
-
identities
Adds multiple identities to the agent.- Parameters:
identities- the identities to add- Returns:
- this builder
-
principal
Attribute every action this agent dispatches toprincipal(TNS-298). The configuredLiabilitySinksees this principal's id / version on every record.Required.
build()throws when this is unset — the framework treats accountability as a deployment decision, not a silent default. UseLocalIdentityProviderfor single-tenant deployments where the framework is the trust boundary, or an external attestation provider (ERC-8004 / X.509 / AIUC-1) when an outside trust root is needed.- Returns:
- this builder
- Since:
- 0.10.0 (TNS-298)
-
liabilitySink
Configure theLiabilitySinkthat receives anAgentLiabilityRecordper dispatch (TNS-298).Optional. When unset, no liability records are constructed or retained.
RecordingLiabilitySinkis an explicit in-memory option for tests; consumers may supply their own retention sink.- Returns:
- this builder
- Since:
- 0.10.0 (TNS-298)
-
authorityScope
Pre-declared authority bounds recorded on every dispatch (TNS-298). Auditors compare attempted actions against this scope to flag scope violations.Required.
build()throws when this is unset. Consumers who deliberately don't want to narrow passAuthorityScope.unrestricted(java.time.Duration)— the explicit-decision-recorded-in-audit path is preferred over a silent default.- Returns:
- this builder
- Since:
- 0.10.0 (TNS-298)
-
paymentBroker
Plug aPaymentBrokerinto this agent (TNS-298 / TNS-449). The broker prices and settles agent-to-agent payments — chain-level rails (x402 viatnsai-payments), card rails (Stripe), or an internal credit ledger.Optional. Unset means the agent uses
NoOpPaymentBroker: quotes at $0.00, settlements succeed instantly, accountability machinery threads through untouched. Suitable for internal multi-agent setups where no real money flows. Auto-discovery is intentionally not provided — a broker that moves real funds must be wired explicitly, never picked up off the classpath.- Returns:
- this builder
- Since:
- 0.11.0 (TNS-449 P4.5)
-
skillStore
Wire aSkillStoreso the agent can surface on-demand modular knowledge between role and tools (TNS-289). When set without an explicitskillResolverPolicy, the policy upgrades fromOFFtoAUTO, which matches the consumer's intent ("I wired a store, surface candidates automatically").- Returns:
- this builder
- Since:
- 0.10.0 (TNS-289)
-
skillResolver
Override the resolver used whenskillResolverPolicyisAUTO. Defaults toKeywordSkillResolver(cheap, no extra round trip). UseLLMSkillResolverfor semantic ranking.- Returns:
- this builder
- Since:
- 0.10.0 (TNS-289)
-
skillResolverPolicy
- Returns:
- this builder
- Since:
- 0.10.0 (TNS-289)
-
maxActiveSkills
Cap the number of skill descriptions surfaced in the system prompt per turn (TNS-289). Defaults to 3 — keeps prompt overhead bounded while still covering the common case where one or two skills are intent-relevant.- Returns:
- this builder
- Throws:
IllegalArgumentException- iflimit< 1- Since:
- 0.10.0 (TNS-289)
-
communication
Sets the communication style for the agent.- Parameters:
communication- the communication style- Returns:
- this builder
-
promptStrategy
Adds a prompt strategy to the agent.Prompt strategies enhance the agent's prompts with techniques like Chain-of-Thought, Verification, Confidence scoring, etc.
Example:
AgentBuilder.create() .llm(llmClient) .role(myRole) .promptStrategy(PromptStrategy.CHAIN_OF_THOUGHT) .promptStrategy(PromptStrategy.CONFIDENCE_WEIGHTED) .build();- Parameters:
strategy- the prompt strategy to add- Returns:
- this builder
-
promptStrategies
Adds multiple prompt strategies to the agent.- Parameters:
strategies- the prompt strategies to add- Returns:
- this builder
-
promptEnhancer
Sets a custom prompt enhancer for the agent.Use this when you need more control than simple strategies provide.
Example:
PromptEnhancer enhancer = PromptEnhancer.builder() .role("Expert researcher") .objective("Provide accurate information") .strategy(PromptStrategy.CHAIN_OF_VERIFICATION) .constraint("Always cite sources") .positiveExample("Question", "Good answer", "Why it's good") .build(); AgentBuilder.create() .llm(llmClient) .role(myRole) .promptEnhancer(enhancer) .build();- Parameters:
enhancer- the prompt enhancer- Returns:
- this builder
-
plan
Adds a plan to the agent.- Parameters:
plan- the plan to add- Returns:
- this builder
-
plans
Adds multiple plans to the agent.- Parameters:
plans- the plans to add- Returns:
- this builder
-
errorRecoveryScenario
Adds an error recovery scenario to the agent.- Parameters:
scenario- the error recovery scenario- Returns:
- this builder
-
errorRecoveryScenarios
Adds multiple error recovery scenarios to the agent.- Parameters:
scenarios- the error recovery scenarios- Returns:
- this builder
-
maxContextTokens
Sets the maximum context tokens for memory pruning.- Parameters:
maxTokens- the maximum context tokens- Returns:
- this builder
-
idempotencyStore
Sets theIdempotencyStoreconsulted for tools guarded by@Idempotent. Defaults to a per-processInMemoryIdempotencyStore. For tools declaredidempotencyHint = REQUIRED(payments, irreversible deletes) pass a durable implementation —RedisIdempotencyStoreorPostgresIdempotencyStore— because the default loses every record on restart, and a lost record is a duplicated effect after recovery (TAN-5933).- Parameters:
store- the store to route through the tool dispatcher- Returns:
- this builder
- Since:
- 0.16.0
-
knowledge
Gives the agent knowledge entries, layered over its@AgentSpecknowledge by name: an entry whose name the annotation declares replaces that entry (a role entry stays a role entry), and any other entry is added to the agent's chat scope. The knowledge rules run on the layered list, so a chat scope still holds one MEMORY entry and no other SEARCH entry beside it. Repeated calls add to the entries already given.- Parameters:
entries- the entries- Returns:
- this builder
- Since:
- 0.18.0
-
actionKnowledge
Names the knowledge one action uses, replacing the list its@ActionSpecnames. Each name refers to an entry of the layered knowledge. The action and the names are checked when the agent first initializes, not bybuild(): an action the agent does not have fails with the list of its actions.- Parameters:
action- the action's nameentryNames- the knowledge names the action uses- Returns:
- this builder
- Since:
- 0.18.0
-
knowledgeScope
Shares action-level source snapshots and ordered cursors with other agents and bridges using the same explicit knowledge scope. The host owns the scope and closes it when that lifetime is replaced; active leased turns finish before its resources are released. When unset, action retrieval retains the existing process-wide behavior.- Parameters:
scope- knowledge-source lifetime, including one closing after this thread's turn has already acquired a lease- Returns:
- this builder
- Since:
- 0.17.4
-
knowledgeUsageListener
Receives what each knowledge source gave every chat turn (scope"chat") and every action call that runs knowledge (scope = the action name): oneKnowledgeUsagerow per source, in declaration order. The listener runs on the calling thread; if it throws, the failure is logged at WARN with the agent id and scope, and the turn or action continues.- Parameters:
listener- receives the scope and the rows- Returns:
- this builder
- Since:
- 0.18.0
-
plannerHandle
Sets the planner handle for goal-oriented planning.If not set and tnsai-intelligence is on the classpath, a PlannerHandle will be auto-discovered via SPI from the first role's class.
- Parameters:
plannerHandle- the planner handle- Returns:
- this builder
-
reasoningStrategy
Sets the reasoning strategy by name (e.g., "react", "tot", "got", "self-consistency").The strategy handle is created via SPI auto-discovery from tnsai-intelligence. If tnsai-intelligence is not on the classpath, this is silently ignored.
- Parameters:
strategyName- the strategy identifier- Returns:
- this builder
-
reasoningStrategy
Sets an explicit reasoning strategy handle.Use this when you have a pre-configured strategy instance. Takes precedence over
reasoningStrategy(String).- Parameters:
strategy- the reasoning strategy handle- Returns:
- this builder
-
toolPojos
Adds tools by reflecting over POJO instances bearing@Tool-annotated methods (the function-shape pattern, see RFC #188). Each discovered@Toolmethod becomes aStaticToolMethodin the agent'sToolMethodRegistryatbuild()time.Example with the server's POJO tools:
Path workingDir = Path.of("/projects/my-app"); AgentBuilder.create() .llm(llmClient) .role(myRole) .toolPojos( new ServerFileTools(workingDir), new ServerShellTools(workingDir), new ServerGitTools(workingDir) ) .build();Multiple calls accumulate. A single
ToolMethodRegistryis built atbuild()time across every POJO and everydynamic tool, so duplicate names across the entire registration set are caught by the registry's fail-fast.- Parameters:
pojos- one or more objects whose public methods are annotated with@Tool- Returns:
- this builder
- Since:
- 0.5.7
-
builtInTools
Adds one or more shippedtoolkits to the agent. Each enum value is reflectively instantiated viainvalid reference
BuiltInTooland registered through the same pipeline asinvalid reference
BuiltInTool#instantiate()toolPojos(Object...). Use this as the compile-time-safe shorthand when the toolkit you want is part of the curated catalog intnsai-tools.Agent agent = AgentBuilder.create() .id("data-analyst") .llm(llmClient) .role(myRole) .builtInTools( BuiltInTool.CSV_TOOLS, BuiltInTool.JSON_TOOLS, BuiltInTool.PDF_TOOLS ) .build();Each invocation accumulates; a single
ToolMethodRegistryis built atbuild()time across every registered toolkit (so duplicate@Toolnames across the selected toolkits are caught by the registry's fail-fast).- Parameters:
tools- one or moreentries to registerinvalid reference
BuiltInTool- Returns:
- this builder
- Throws:
BuiltInToolInstantiationException- if a backing POJO class is missing from the classpath (typically becausetnsai-toolsis not a runtime dependency)- Since:
- 0.8.0
-
dynamicTool
Adds aDynamicToolMethod— a tool whose name, description, schema, and dispatch handler are all supplied at construction time. Use for tools whose identity is only known at runtime (e.g. MCP proxies fronting remote server catalogs).For static
@Tool-annotated methods on POJOs, prefertoolPojos(Object...).- Parameters:
dynamicTool- the runtime-defined tool (non-null)- Returns:
- this builder
- Since:
- 0.7.0 (replaced the legacy
tool(Tool)/tools(List<Tool>)registration paths together with theToolinterface itself)
-
dynamicTools
- Parameters:
dynamicTools- the runtime-defined tools (may be empty)- Returns:
- this builder
- Since:
- 0.7.0
-
toolCallFilter
Pre-build wiring of aToolCallFilter— the runtime gate consulted before each tool invocation. Equivalent to callingAgent.setToolCallFilter(com.tnsai.agents.execution.ToolCallFilter)afterbuild(), but visible to the validation pipeline soToolApprovalValidator(AGENT-V006) can detect when a tool declares@Tool(requiresConfirmation = true)but no approval filter is configured.- Parameters:
filter- the filter, ornullto clear- Returns:
- this builder
- Since:
- 0.8.5 (issue #234)
-
tenantId
Declares the tenant this agent is scoped to. The tenant id is plumbed through the validation context soAGENT-V012(TenantScopeValidator) can complain when the agent is wired to a component that does not implementTenantAware.At runtime, public agent turns bind the value to
TenantContext. Memory stores that implementTenantAwareare guarded against calls with a missing or mismatched tenant scope. Tool-side tenant hooks and tenant fields on audit events remain separate work.Pass
nullor blank to clear (treated as "no tenant scope").- Parameters:
tenantId- stable, non-blank identifier for the tenant; ornull/blank to clear- Returns:
- this builder
- Since:
- 0.8.5 (issue #235)
-
build
Builds and returns the configured Agent instance.Runs the pre-flight validation pipeline (issue #85) first. Every detected
Severity.ERRORis collected into aValidationReportand surfaced together viaAgentValidationException. Warnings are logged atWARNbut do not block the build.- Returns:
- the configured Agent
- Throws:
AgentValidationException- if the pipeline detects any error-level issues
-
relaxValidation
Suppress a specificValidationIssue.code()from thebuild()pipeline. Use sparingly and document each suppression — this is the explicit, auditable opt-out for unusual configurations the validators flag but the user has decided are intentional.- Parameters:
issueCode- validator code to ignore (e.g."AGENT-V002")- Returns:
- this builder
- Since:
- 0.5.0 (issue #85)
-
relaxValidation
Bulk variant ofrelaxValidation(String)(issue #85 phase 3 acceptance bullet). Identical semantics, accepts aSetof codes for the common case of suppressing several validators at once (e.g. CI build that wants to skip all reachability probes:.relaxValidation(Set.of("AGENT-V005", "AGENT-V010", "AGENT-V099"))).Null entries in the set are rejected eagerly so a typo surfaces at the configuration site rather than silently passing every issue through.
- Parameters:
issueCodes- validator codes to ignore; non-null and non-null contents- Returns:
- this builder
- Since:
- 0.8.5 (issue #85 phase 3)
-
withReachabilityChecks
Enable opt-in reachability probes duringbuild()(issue #85 phase 2a). Whentrue, everyReachabilityValidatorregistered on the pipeline runs in parallel after the sync validators, each bounded byreachabilityCheckTimeout(Duration).Default
false. The probes touch out-of-process resources (network call to the LLM provider, write to the memory store, MCP handshake) — turn this on in CI or staging environments where you want build-time confirmation that runtime dependencies are actually reachable, leave it off in tests where the probes would spend money or perturb state.- Since:
- 0.8.4 (issue #85 phase 2a)
-
reachabilityCheckTimeout
Per-probe wall-clock budget passed to eachReachabilityValidatorwhen reachability checks are enabled. Default 5 seconds. Probes that exceed this budget are reported as unreachable (timeout) and the validation pipeline continues.- Since:
- 0.8.4 (issue #85 phase 2a)
-
validateFully
Run the full validator pipeline against the current builder state and return the resultingValidationReport. Public so tests and callers that want the report without throwing can introspect issues. Codes added viarelaxValidation(String)are filtered out before the report is returned.- Since:
- 0.5.0 (issue #85)
-