Java SDK quickstart
Register a Java agent with AIM, gate actions with capability checks, and log to the AIM audit trail. Compatible with LangChain4j and Spring AI.
Prerequisites
- • AIM running at
http://localhost:8080(see Installation) - • Java 17+ and Maven or Gradle
- • SDK token from AIM Dashboard (Settings → SDK Tokens)
Add the dependency
Add the AIM SDK with Maven or Gradle:
Maven
<dependency>
<groupId>org.opena2a</groupId>
<artifactId>aim-sdk</artifactId>
<version>1.0.0</version>
</dependency>Gradle
implementation 'org.opena2a:aim-sdk:1.0.0'Local installation: for a local JAR, install with mvn install:install-file -Dfile=aim-sdk-1.0.0.jar -DgroupId=org.opena2a -DartifactId=aim-sdk -Dversion=1.0.0 -Dpackaging=jar.
Initialize the SDK
Build an AIMClient and register the agent:
import org.opena2a.aim.client.AIMClient;
import org.opena2a.aim.client.AgentType;
import java.util.Arrays;
public class MyAgent {
public static void main(String[] args) {
// Initialize client with builder pattern
AIMClient agent = AIMClient.builder("my-java-agent")
.agentType(AgentType.LANGCHAIN)
.capabilities(Arrays.asList("data:read", "api:call"))
.build();
System.out.println("Agent registered: " + agent.getAgentId());
System.out.println("Trust Score: " + agent.getAgentDetails().get("trustScore"));
}
}The SDK uses a get-or-create pattern, so repeated registerAgent calls are idempotent.
Gate actions with @SecureAction
Annotate methods with @SecureAction to enforce capability checks and write to the audit trail:
import org.opena2a.aim.annotations.SecureAction;
import org.opena2a.aim.client.RiskLevel;
public class WeatherService {
@SecureAction(capability = "weather:fetch")
public String getWeather(String city) {
// This action is now verified, logged, and monitored
return "Weather in " + city + ": Sunny, 72°F";
}
@SecureAction(
capability = "notification:send",
riskLevel = RiskLevel.HIGH
)
public void sendWeatherAlert(String userId, String message) {
// High-risk actions get additional monitoring
System.out.println("Sending alert to " + userId + ": " + message);
}
@SecureAction(
capability = "db:delete",
riskLevel = RiskLevel.CRITICAL,
jitAccess = true // Requires admin approval
)
public void purgeOldData(int daysOld) {
// Blocks until an admin approves the request in the dashboard
System.out.println("Purging data older than " + daysOld + " days");
}
}jitAccess = true, the call blocks until an admin approves the request in the AIM dashboard.LangChain4j integration
Wrap LangChain4j tools with @SecureAction:
import dev.langchain4j.agent.tool.Tool;
import org.opena2a.aim.annotations.SecureAction;
public class SecuredLangChain4jTools {
@Tool("Fetch current weather for a city")
@SecureAction(capability = "weather:fetch")
public String getWeather(String city) {
return "Weather in " + city + ": Sunny";
}
@Tool("Search the knowledge base")
@SecureAction(capability = "kb:search")
public String searchKnowledgeBase(String query) {
return "Results for: " + query;
}
}Additional security helpers
The Java SDK ships three optional helpers:
SecurityLogger
Structured audit logging with automatic context capture.
RiskDetector
Pattern-based risk assessment for capabilities and actions.
AttestationCache
In-memory cache for MCP server attestations.
import org.opena2a.aim.security.SecurityLogger;
import org.opena2a.aim.security.RiskDetector;
import org.opena2a.aim.security.RiskLevel;
import org.opena2a.aim.mcp.AttestationCache;
// Audit logging
SecurityLogger logger = SecurityLogger.getInstance();
logger.logAuthentication(EventTypes.Authn.TOKEN_REFRESH, true, "Refreshed", Map.of());
// Risk detection (pattern-based)
RiskDetector detector = RiskDetector.getInstance();
RiskLevel level = detector.detectRisk("payment:charge"); // Returns: HIGH
// Attestation cache for MCP drift detection
AttestationCache cache = AttestationCache.getInstance();
cache.store("mcp-server-id", discovery, "attestation-123");Complete example
import org.opena2a.aim.client.AIMClient;
import org.opena2a.aim.client.AgentType;
import org.opena2a.aim.client.RiskLevel;
import org.opena2a.aim.annotations.SecureAction;
import java.util.Arrays;
public class WeatherBot {
private final AIMClient agent;
public WeatherBot() {
this.agent = AIMClient.builder("weather-bot-java")
.agentType(AgentType.LANGCHAIN)
.capabilities(Arrays.asList("weather:fetch", "notification:send"))
.build();
}
@SecureAction(capability = "weather:fetch")
public String getWeather(String city) {
return "Weather in " + city + ": Sunny, 72°F";
}
@SecureAction(
capability = "notification:send",
riskLevel = RiskLevel.HIGH
)
public void sendAlert(String userId, String message) {
System.out.println("Alert to " + userId + ": " + message);
}
public static void main(String[] args) {
WeatherBot bot = new WeatherBot();
// Every annotated call is gated and logged
String weather = bot.getWeather("San Francisco");
System.out.println(weather);
bot.sendAlert("user-123", "Temperature is 72F");
System.out.println("Actions logged to AIM");
}
}