Inicio Rápido de Java
Construye tu primer agente de IA y flujo de trabajo en Java con JamJet — herramientas, estrategias, ejecución duradera y compilación IR.
Guía Rápida de Java
Esta guía te lleva paso a paso en la construcción de un agente de IA y un flujo de trabajo duradero en Java. Al finalizar comprenderás cómo se integran las herramientas de JamJet, las estrategias de agente, la compilación de IR y el estado de flujo de trabajo tipado — y por qué cada decisión de diseño importa para sistemas de agentes en producción.
Requisitos previos
Antes de comenzar, asegúrate de tener:
- Java 21+ — JamJet utiliza hilos virtuales (
Thread.ofVirtual) para I/O no bloqueante sin maraña de callbacks. Los hilos virtuales son una característica final (no preview) en Java 21 (JEP 444). - Maven 3.9+ o Gradle 8+ — cualquier herramienta de construcción que pueda obtener dependencias desde Maven Central.
- Un runtime de JamJet en ejecución — para ejecución en producción. Durante el desarrollo puedes ejecutar todo en el mismo proceso (sin servidor requerido), o iniciar el runtime local con:
jamjet dev - Una clave de API de LLM — configura
OPENAI_API_KEYoANTHROPIC_API_KEYen tu entorno. Para desarrollo exclusivamente local, Ollama funciona sin ninguna clave.
consejo: Puedes seguir toda esta guía sin un runtime en ejecución. El ejecutor en proceso te permite compilar, validar y ejecutar flujos de trabajo localmente. Agrega el runtime cuando necesites recuperación ante fallos y estado duradero.
Agregar la dependencia
El SDK de Java está publicado en Maven Central como dev.jamjet:jamjet-sdk.
Maven
<dependency>
<groupId>dev.jamjet</groupId>
<artifactId>jamjet-sdk</artifactId>
<version>0.4.0</version>
</dependency>Gradle (Kotlin DSL)
implementation("dev.jamjet:jamjet-sdk:0.4.0")Gradle (Groovy DSL)
implementation 'dev.jamjet:jamjet-sdk:0.4.0'Asegúrate de que tu proyecto esté configurado para Java 21 o posterior. En Maven:
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>Definir una herramienta
Las herramientas son el puente entre tu agente y el mundo exterior — búsqueda web, consultas de base de datos, llamadas a APIs, I/O de archivos. En JamJet, una herramienta es un record de Java anotado con @Tool que implementa ToolCall<T>.
import dev.jamjet.tool.Tool;
import dev.jamjet.tool.ToolCall;
@Tool(description = "Buscar en la web información sobre un tema")
record WebSearch(String query) implements ToolCall<String> {
public String execute() {
// En producción, llama a tu API de búsqueda aquí
return "Resultados para '" + query + "': JamJet es un runtime y framework "
+ "nativo para agentes de IA, centrado en rendimiento.";
}
}¿Por qué records?
Este diseño es intencional. Los records de Java te brindan tres propiedades que importan para las herramientas de agentes:
-
Inmutabilidad — los parámetros de una llamada a herramienta nunca cambian después de la construcción. Esto hace que las llamadas a herramientas sean seguras para serializar, reproducir y auditar. Cuando JamJet reproduce un flujo de trabajo fallido, vuelve a invocar la misma llamada a herramienta con exactamente los mismos parámetros.
-
Derivación automática de JSON Schema — el SDK inspecciona los componentes del record (
String queryarriba) y genera el JSON Schema que el LLM necesita para invocar la herramienta. Sin escritura manual de esquemas, sin sobrecarga de anotaciones, sin desincronización entre tu código y tu esquema. -
Igualdad estructural — dos instancias de
WebSearch("jamjet")son iguales. Esto permite la deduplicación y el almacenamiento en caché de llamadas a herramientas entre reintentos.
La anotación @Tool proporciona la description que el LLM ve al decidir qué herramienta usar. Escríbela como si explicaras la herramienta a un colega — clara, específica, orientada a la acción.
nota: Para una cobertura más profunda de patrones de diseño de herramientas, estrategias de agentes y cuándo usar cada una — consulta Patrones de IA Agéntica.
Construye un agente
Un agente combina un modelo, herramientas, instrucciones y una estrategia de razonamiento. La estrategia determina cómo piensa el agente — no solo qué hace.
import dev.jamjet.agent.Agent;
var agent = Agent.builder("researcher")
.model("claude-haiku-4-5-20251001")
.tools(WebSearch.class)
.instructions("Eres un asistente de investigación útil. "
+ "Siempre busca primero, luego proporciona un resumen exhaustivo.")
.strategy("react")
.maxIterations(5)
.build();Desglosemos cada parte.
La estrategia react
Cuando estableces .strategy("react"), le estás indicando a JamJet que use el bucle ReAct (Razonamiento + Actuación):
- Pensamiento — el modelo razona sobre qué hacer a continuación
- Acción — el modelo llama a una herramienta
- Observación — el resultado de la herramienta se retroalimenta al modelo
- Repetir hasta que el modelo produzca una respuesta final o alcance el límite de iteraciones
Esta es la estrategia de agente más común porque es flexible: el modelo decide dinámicamente qué herramientas llamar y en qué orden. Funciona bien para tareas abiertas donde no puedes predecir la secuencia exacta de pasos.
JamJet admite tres estrategias integradas:
| Estrategia | Cuándo usar | Cómo funciona |
|---|---|---|
react | Tareas abiertas, investigación exploratoria | Bucle pensamiento-acción-observación |
plan-and-execute | Tareas estructuradas que se benefician de planificación previa | Genera plan, luego ejecuta cada paso secuencialmente |
critic | Tareas que requieren control de calidad | Bucle borrador, crítica, revisión |
consejo: ¿No estás seguro qué estrategia elegir? Comienza con
react. Actualiza aplan-and-executecuando veas que el agente divaga, o acriticcuando la calidad del resultado importe más que la velocidad. Consulta comparaciones de estrategias en jamjet.dev/research para ver benchmarks.
Barreras de protección: costo, tiempo e iteraciones
Los agentes en producción necesitan límites estrictos. Sin ellos, un modelo confundido puede quemar tu presupuesto de API en un bucle:
var agent = Agent.builder("investment-researcher")
.model("gpt-4o")
.tools(WebSearch.class, FetchUrl.class, StoreNote.class)
.instructions("""
Eres un analista profesional de investigación de inversiones.
Busca noticias recientes y datos financieros, luego produce
un memorándum de inversión estructurado.
""")
.strategy("plan-and-execute")
.maxIterations(6)
.maxCostUsd(0.50)
.timeoutSeconds(120)
.build();maxIterations(6)— el agente se detiene después de 6 pasos de razonamiento, incluso si no ha terminado. Esto previene bucles infinitos.maxCostUsd(0.50)— el runtime rastrea los costos de tokens en tiempo real y detiene al agente si el gasto excede los 50 centavos.timeoutSeconds(120)— timeout de tiempo real. Si el agente no ha completado en 2 minutos, la ejecución se aborta.
Estos no son sugerencias — son límites estrictos aplicados por el runtime. El runtime de JamJet los verifica entre cada paso, no solo al final.
Ejecútalo
Con el agente construido, puedes ejecutarlo e inspeccionar los resultados:
public static void main(String[] args) {
var agent = Agent.builder("researcher")
.model("claude-haiku-4-5-20251001")
.tools(WebSearch.class)
.instructions("Eres un asistente de investigación útil. "
+ "Siempre busca primero, luego proporciona un resumen exhaustivo.")
.strategy("react")
.maxIterations(5)
.build();
// Ejecutar el agente
var result = agent.run("¿Qué es JamJet?");
System.out.println(result.output());
System.out.printf("Duración: %.2f ms%n", result.durationUs() / 1000.0);
System.out.printf("Llamadas a herramientas: %d%n", result.toolCalls().size());
}export OPENAI_API_KEY=sk-...
mvn compile exec:java -Dexec.mainClass=com.example.MyAgentCompilación IR: qué ocurre bajo el capó
Antes de que tu agente se ejecute, JamJet lo compila a una representación intermedia (IR) — un formato de grafo canónico compartido entre el SDK de Java, el SDK de Python y los flujos de trabajo YAML. Puedes inspeccionar el IR directamente:
var ir = agent.compile();
System.out.println("workflow_id: " + ir.id());
System.out.println("start_node: " + ir.startNode());
System.out.println("nodes: " + ir.nodes().size());
System.out.println("edges: " + ir.edges().size());Esto imprime algo como:
workflow_id: researcher
start_node: react_start
nodes: 3
edges: 4¿Por qué importa esto? Porque el IR es lo que el runtime de JamJet realmente ejecuta. Ya sea que escribas tu agente en Java, Python o YAML, se compila al mismo formato de grafo. Esto significa:
- Portabilidad — un agente escrito en Java puede desplegarse en cualquier runtime de JamJet
- Inspección — puedes validar y visualizar el grafo de ejecución antes de ejecutarlo
- Durabilidad — el runtime crea checkpoints en los límites de nodos, por lo que puede reanudarse después de un fallo
También puedes validar el IR antes del envío:
import dev.jamjet.ir.IrValidator;
IrValidator.validateOrThrow(ir);Esto detecta problemas estructurales (nodos desconectados, aristas faltantes, esquemas de estado inválidos) en tiempo de compilación en lugar de en tiempo de ejecución.
Construye un flujo de trabajo
Los agentes son ideales para tareas abiertas donde el modelo decide qué hacer. Pero muchos sistemas del mundo real necesitan pipelines determinísticos de múltiples pasos — enriquecimiento de datos, RAG, cadenas de aprobación, ETL. Para estos casos, usa un Workflow.
La diferencia clave: en un agente, el LLM decide la ruta de ejecución. En un flujo de trabajo, tú decides la ruta de ejecución y el LLM es solo un paso en el pipeline.
Aquí hay un flujo de trabajo RAG (Generación Aumentada por Recuperación) de dos pasos:
import dev.jamjet.workflow.Workflow;
import java.util.List;
// Estado tipado — un record de Java
record RagState(
String query,
List<String> retrievedDocs,
String answer) {}
var workflow = Workflow.<RagState>builder("rag-assistant")
.version("1.0.0")
.state(RagState.class)
// Paso 1: Recuperar documentos relevantes
.step("retrieve", state -> {
var docs = searchKnowledgeBase(state.query());
return new RagState(state.query(), docs, null);
})
// Paso 2: Sintetizar una respuesta a partir del contexto
.step("synthesize", state -> {
var context = String.join("\n\n", state.retrievedDocs());
var answer = callLlm(state.query(), context);
return new RagState(state.query(), state.retrievedDocs(), answer);
})
.build();Cómo fluye el estado a través de un flujo de trabajo
Cada paso recibe el RagState actual y devuelve un nuevo RagState. El estado es siempre inmutable — nunca mutas el record existente, construyes uno nuevo. Esto es lo que hace que los flujos de trabajo sean durables: si el runtime falla entre "retrieve" y "synthesize", se reanuda desde el último checkpoint completado con el estado exacto que fue persistido.
Así es como se ejecuta este flujo de trabajo:
graph LR
A["Start"] --> B["retrieve"]
B --> C["synthesize"]
C --> D["End"]El paso "retrieve" llena retrievedDocs. El paso "synthesize" los lee y produce la answer final. Cada paso tiene un checkpoint — si el proceso falla después de que "retrieve" se complete, el runtime se reanuda en "synthesize" sin volver a ejecutar la recuperación.
Ejecutando el flujo de trabajo
import dev.jamjet.workflow.ExecutionResult;
import java.util.ArrayList;
var initialState = new RagState(
"How does JamJet handle concurrent tool calls?",
new ArrayList<>(),
null);
ExecutionResult<RagState> result = workflow.run(initialState);
System.out.println(result.state().answer());
System.out.printf("Ran %d steps in %.2f ms%n",
result.stepsExecuted(), result.totalDurationUs() / 1000.0);Agent vs Workflow: cuándo usar cada uno
| Agent | Workflow | |
|---|---|---|
| Flujo de control | El LLM decide | Tú decides |
| Ideal para | Tareas abiertas, investigación, chat | Pipelines, RAG, cadenas de aprobación, ETL |
| Determinismo | No determinista (guiado por modelo) | Determinista (guiado por código) |
| Durabilidad | Checkpoints en límites de estrategia | Checkpoints en cada paso |
| Herramientas | El modelo elige qué herramientas llamar | Los pasos llaman herramientas explícitamente |
Puedes combinar ambos: usa un workflow como orquestador externo e integra agents dentro de pasos individuales. Esto te da pipelines deterministas con subpasos inteligentes.
Próximos pasos
Ahora tienes un agent y un workflow funcionando. Aquí tienes dónde profundizar:
- Referencia del SDK de Java — cobertura completa de la API: enrutamiento condicional, evaluación, gestión de estado, cliente de runtime, agents basados en anotaciones
- Guía del Spring Boot Starter — integra JamJet con Spring AI, Spring Security y observabilidad con Micrometer
- Integración con LangChain4j — usa JamJet como capa de ejecución durable para agents de LangChain4j
- Conceptos Fundamentales — agents, nodos, estado y durabilidad en profundidad
- Ejemplos en GitHub — ejemplos ejecutables incluyendo flujo básico de herramientas, agent plan-and-execute y asistente RAG
- Patrones de IA Agéntica — selección de estrategias, diseño de herramientas y patrones de producción para sistemas agénticos
consejo: ¿Ya usas Spring Boot? Avanza directamente a la Guía del Spring Boot Starter — envuelve todo lo de este inicio rápido en autoconfiguración con health checks, métricas y registros de auditoría.