1. স্বাগতম, এআই এজেন্ট ডেভেলপার!
এই কোডল্যাবে, আপনি জাভা-এর জন্য এজেন্ট ডেভেলপমেন্ট কিট (ADK) ব্যবহার করে জাভাতে AI এজেন্ট কীভাবে তৈরি করবেন তা শিখবেন। আমরা সহজ লার্জ ল্যাঙ্গুয়েজ মডেল (LLM) API কলের বাইরে চলে যাব স্বায়ত্তশাসিত AI এজেন্ট তৈরি করতে যা যুক্তি দিতে পারে, পরিকল্পনা করতে পারে, টুল ব্যবহার করতে পারে এবং জটিল সমস্যার সমাধান করতে একসঙ্গে কাজ করতে পারে।
আপনি Google ক্লাউড ক্রেডিটগুলি রিডিম করে শুরু করবেন, আপনার Google ক্লাউড পরিবেশ সেট আপ করবেন, তারপর আপনার প্রথম সাধারণ এজেন্ট তৈরি করবেন এবং ক্রমান্বয়ে কাস্টম টুল, ওয়েব অনুসন্ধান এবং মাল্টি-এজেন্ট অর্কেস্ট্রেশনের মতো আরও উন্নত ক্ষমতা যুক্ত করবেন৷
আপনি কি শিখবেন
- কীভাবে একটি মৌলিক, ব্যক্তি-চালিত এআই এজেন্ট তৈরি করবেন।
- কাস্টম এবং বিল্ট-ইন টুল (যেমন Google অনুসন্ধান) দিয়ে এজেন্টকে কীভাবে ক্ষমতায়ন করা যায়।
- জাভাতে বাস্তবায়িত আপনার নিজস্ব সরঞ্জামগুলি কীভাবে যুক্ত করবেন।
- কিভাবে একাধিক এজেন্টকে শক্তিশালী অনুক্রমিক, সমান্তরাল এবং লুপিং ওয়ার্কফ্লোতে অর্কেস্ট্রেট করা যায়।
আপনি কি প্রয়োজন হবে
- একটি ওয়েব ব্রাউজার যা আমরা ছদ্মবেশী মোডে ব্যবহার করব।
- একটি ব্যক্তিগত জিমেইল অ্যাকাউন্ট।
- আপনার ব্যক্তিগত Gmail অ্যাকাউন্টের সাথে যুক্ত একটি নতুন Google ক্লাউড প্রকল্প৷
- রিডিম করা Google ক্লাউড ক্রেডিট দিয়ে একটি বিলিং অ্যাকাউন্ট তৈরি করা হয়েছে।
- সোর্স কোড পরীক্ষা করার জন্য গিট কমান্ড-লাইন টুল।
- Java 17+ এবং Apache Maven।
- একটি পাঠ্য সম্পাদক বা IDE, যেমন IntelliJ IDEA বা VS কোড।
Google ক্লাউড কনসোলে ক্লাউড শেল-এ অন্তর্নির্মিত VS কোড সম্পাদক ব্যবহার করা সম্ভব।
2. সেটআপ: আপনার পরিবেশ
ওয়ার্কশপের জন্য Google ক্লাউড ক্রেডিট দাবি করা
একটি প্রশিক্ষকের নেতৃত্বে কর্মশালার জন্য, আপনি ওয়েবসাইটের একটি লিঙ্ক পাবেন যেখানে আপনি কর্মশালার জন্য ব্যবহার করার জন্য Google ক্লাউড ক্রেডিট দাবি করতে পারেন।
- একটি ব্যক্তিগত Google অ্যাকাউন্ট ব্যবহার করুন : কর্পোরেট বা স্কুল ইমেল ঠিকানাগুলি কাজ করবে না বলে একটি ব্যক্তিগত Google অ্যাকাউন্ট (যেমন একটি gmail.com ঠিকানা) ব্যবহার করা গুরুত্বপূর্ণ।
- ছদ্মবেশী মোডে Google Chrome ব্যবহার করুন : এটি একটি পরিষ্কার সেশন তৈরি করতে এবং অন্যান্য Google অ্যাকাউন্টগুলির সাথে দ্বন্দ্ব প্রতিরোধ করার জন্য সুপারিশ করা হয়৷
- বিশেষ ইভেন্ট লিঙ্ক ব্যবহার করুন : ইভেন্টের জন্য একটি বিশেষ লিঙ্ক, যা দেখতে https://trygcp.dev/event/xxx এর মতো একটি ইভেন্ট কোড (এই উদাহরণে এখানে "xxx") ব্যবহার করা উচিত।
- পরিষেবার শর্তাদি স্বীকার করুন : সাইন ইন করার পরে, আপনাকে Google ক্লাউড প্ল্যাটফর্মের পরিষেবার শর্তাবলী উপস্থাপন করা হবে, যা চালিয়ে যেতে আপনাকে স্বীকার করতে হবে৷
- একটি নতুন প্রকল্প তৈরি করুন : Google ক্লাউড কনসোল থেকে একটি নতুন খালি প্রকল্প তৈরি করতে হবে৷
- একটি বিলিং অ্যাকাউন্ট লিঙ্ক করুন : একটি বিলিং অ্যাকাউন্টের সাথে নতুন তৈরি প্রকল্প লিঙ্ক করুন।
- ক্রেডিট নিশ্চিত করুন : নিম্নলিখিত ভিডিওটি বিলিং পৃষ্ঠায় "ক্রেডিট" বিভাগটি চেক করে কীভাবে প্রকল্পে ক্রেডিট প্রয়োগ করা হয়েছে তা নিশ্চিত করতে দেখায়।
নির্দ্বিধায় এই ভিডিওটি দেখুন যা ব্যাখ্যা করে যে কীভাবে ক্রেডিটগুলি রিডিম করা যায় এবং প্রয়োগ করা যায়৷
আপনার API কী তৈরি করুন এবং কনফিগার করুন
এই কোডল্যাবের জন্য Gemini API-এর সাথে আপনার ADK AI এজেন্টদের প্রমাণীকরণ করতে, আপনি আপনার Google ক্লাউড প্রকল্পের সাথে যুক্ত একটি API কী ব্যবহার করবেন।
- একটি API কী তৈরি করুন:
- গুগল এআই স্টুডিওতে যান এবং বাম পাশের প্যানেলের নীচে "এপিআই কী পান" লিঙ্কটিতে ক্লিক করুন।
- প্রকল্পগুলি নির্বাচন করুন এবং তারপরে আমদানি প্রকল্প বোতামে ক্লিক করুন।
- আপনি যে Google ক্লাউড প্রকল্পটি আমদানি করতে চান সেটি অনুসন্ধান করুন এবং নির্বাচন করুন , তারপর আমদানি বোতামটি নির্বাচন করুন৷
- একবার প্রজেক্ট ইম্পোর্ট করা হয়ে গেলে, ড্যাশবোর্ড মেনু থেকে API কী পৃষ্ঠায় যান এবং আপনি এইমাত্র যে প্রোজেক্টটি আমদানি করেছেন তাতে একটি API কী তৈরি করুন।
- API কী নোট করুন ।
- এনভায়রনমেন্ট ভেরিয়েবল সেট করুন: আপনার এজেন্টকে এই কী অ্যাক্সেস করতে হবে। আদর্শ উপায় হল
GOOGLE_API_KEY
নামের একটি পরিবেশ পরিবর্তনশীল সেট করা।
- macOS / Linux: আপনার টার্মিনাল খুলুন এবং
"your-api-key"
প্রতিস্থাপন করে নিম্নলিখিত কমান্ডটি চালান যা আপনি এইমাত্র কপি করেছেন। এটিকে স্থায়ী করতে, আপনার শেলের স্টার্টআপ ফাইলে এই লাইনটি যোগ করুন (যেমন,~/.bash_profile
,~/.zshrc
)।
export GOOGLE_API_KEY="your-api-key"
- উইন্ডোজ (কমান্ড প্রম্পট): একটি নতুন কমান্ড প্রম্পট খুলুন এবং চালান:
setx GOOGLE_API_KEY "your-api-key"
- এই পরিবর্তন কার্যকর করার জন্য আপনাকে আপনার কমান্ড প্রম্পট পুনরায় চালু করতে হবে।
- উইন্ডোজ (পাওয়ারশেল): একটি পাওয়ারশেল টার্মিনাল খুলুন এবং চালান:
$env:GOOGLE_API_KEY="your-api-key"
- PowerShell-এ এই পরিবর্তনটি স্থায়ী করতে, আপনাকে এটি আপনার প্রোফাইল স্ক্রিপ্টে যোগ করতে হবে।
3. শুরু করা: আপনার প্রথম এজেন্ট
একটি নতুন প্রকল্প শুরু করার সর্বোত্তম উপায় হল Java GitHub টেমপ্লেটের জন্য ADK ব্যবহার করা। এটি প্রকল্পের কাঠামো এবং সমস্ত প্রয়োজনীয় নির্ভরতা প্রদান করে।
আপনার যদি একটি Github অ্যাকাউন্ট থাকে, আপনি নিম্নলিখিতগুলি করতে পারেন: Use this template
> Create a new repository
, তারপর git clone
কমান্ড দিয়ে স্থানীয়ভাবে কোডটি চেকআউট করুন।
এখানে টেমপ্লেট ব্যবহার করার জন্য উপরের-ডান মেনু দেখানো একটি স্ক্রিনশট।
অন্য পদ্ধতিটি হল সেই সংগ্রহস্থলটি সরাসরি ক্লোন করা, এর সাথে:
git clone https://github.com/glaforge/adk-java-maven-template.git
তারপর adk-java-maven-template
cd
।
আপনি জাভাতে আপনার প্রথম এআই এজেন্ট কোডিং শুরু করতে প্রস্তুত কিনা তা পরীক্ষা করতে, নিশ্চিত করুন যে আপনি এই প্রকল্পে কোডটি এর সাথে কম্পাইল করতে পারেন:
mvn compile
কোড ধাপ: একটি বন্ধুত্বপূর্ণ বিজ্ঞান শিক্ষক এজেন্ট
ADK-এর মৌলিক বিল্ডিং ব্লক হল LlmAgent
ক্লাস। একটি বৃহৎ ভাষার মডেল দ্বারা চালিত একটি নির্দিষ্ট ব্যক্তিত্ব এবং লক্ষ্য সহ একটি AI হিসাবে এটিকে ভাবুন৷ আমরা পরে সরঞ্জামগুলির মাধ্যমে আরও ক্ষমতা যুক্ত করব এবং অন্যান্য অনুরূপ এজেন্টদের সাথে হাতে হাত মিলিয়ে এটিকে আরও শক্তিশালী করে তুলব।
আসুন com.example.agent
প্যাকেজে একটি নতুন জাভা ক্লাস তৈরি করি এবং এটিকে ScienceTeacher
বলি।
এই "হ্যালো, বিশ্ব!" এজেন্ট সৃষ্টির। আমরা একজন বিজ্ঞান শিক্ষকের ব্যক্তিত্বের সাথে একটি সাধারণ এজেন্টকে সংজ্ঞায়িত করছি।
// src/main/java/com/example/agent/ScienceTeacher.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.web.AdkWebServer;
public class ScienceTeacher {
public static void main(String[] args) {
AdkWebServer.start(
LlmAgent.builder()
.name("science-teacher")
.description("A friendly science teacher")
.instruction("""
You are a science teacher for teenagers.
You explain science concepts in a simple, concise and direct way.
""")
.model("gemini-2.5-flash")
.build()
);
}
}
AI এজেন্ট LlmAgent.builder()
পদ্ধতির মাধ্যমে কনফিগার করা হয়েছে। name()
, description()
, এবং model()
প্যারামিটারগুলি বাধ্যতামূলক, এবং আপনার এজেন্টকে একটি নির্দিষ্ট ব্যক্তিত্ব এবং সঠিক আচরণ দিতে, আপনাকে সর্বদা instruction()
পদ্ধতির মাধ্যমে বিস্তারিত নির্দেশনা দিতে হবে।
এখানে আমরা জেমিনি 2.5 ফ্ল্যাশ মডেল ব্যবহার করতে বেছে নিয়েছি, তবে আরও জটিল কাজের জন্য জেমিনি 2.5 প্রো ব্যবহার করে দেখতে নির্দ্বিধায়।
এই এজেন্টটি AdkWebServer.start()
পদ্ধতির মধ্যে মোড়ানো হয়। এটি তথাকথিত ADK Dev UI চ্যাট ইন্টারফেস। এটি আপনাকে একটি সাধারণ চ্যাট ইন্টারফেসের মাধ্যমে এজেন্টের সাথে কথোপকথন করতে দেয়। তদ্ব্যতীত, আপনি যদি বুঝতে চান যে হুডের নীচে কী ঘটছে, যেমন সমস্ত ইভেন্ট যা সিস্টেমের মধ্য দিয়ে প্রবাহিত হচ্ছে, এলএলএম-এ পাঠানো অনুরোধ এবং প্রতিক্রিয়া।
স্থানীয়ভাবে এই এজেন্টটি কম্পাইল এবং চালাতে, নিম্নলিখিত কমান্ডটি চালান:
mvn compile exec:java -Dexec.mainClass=com.example.agent.ScienceTeacher
তারপর http://localhost:8080 এ আপনার ব্রাউজারে যান। নীচের স্ক্রিনশটে দেখানো হিসাবে আপনার UI দেখতে হবে। এগিয়ে যান এবং আপনার এজেন্টকে বিজ্ঞান সম্পর্কিত প্রশ্ন জিজ্ঞাসা করুন।
4. সরঞ্জাম সহ এজেন্টদের ক্ষমতায়ন
কেন এজেন্টদের সরঞ্জাম প্রয়োজন? এলএলএম শক্তিশালী, কিন্তু তাদের জ্ঞান সময়ের সাথে হিমায়িত হয় এবং তারা বাইরের বিশ্বের সাথে যোগাযোগ করতে পারে না। হাতিয়ার হল সেতু। তারা একজন এজেন্টকে রিয়েল-টাইম তথ্য অ্যাক্সেস করার অনুমতি দেয় (যেমন স্টকের দাম বা খবর), ব্যক্তিগত API জিজ্ঞাসা করতে বা জাভাতে আপনি কোড করতে পারেন এমন কোনও কাজ সম্পাদন করতে পারেন।
কোড ধাপ: একটি কাস্টম টুল তৈরি করা ( StockTicker
)
এখানে, আমরা আমাদের এজেন্টকে স্টকের দাম দেখার জন্য একটি টুল দিই। এজেন্ট যুক্তি দেয় যে যখন একজন ব্যবহারকারী একটি মূল্য জিজ্ঞাসা করে, তখন এটি আমাদের জাভা পদ্ধতিতে কল করা উচিত।
// src/main/java/com/example/agent/StockTicker.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.Annotations.Schema;
import com.google.adk.tools.FunctionTool;
import com.google.adk.web.AdkWebServer;
import java.util.Map;
public class StockTicker {
public static void main(String[] args) {
AdkWebServer.start(
LlmAgent.builder()
.name("stock_agent")
.instruction("""
You are a stock exchange ticker expert.
When asked about the stock price of a company,
use the `lookup_stock_ticker` tool to find the information.
""")
.model("gemini-2.5-flash")
.tools(FunctionTool.create(StockTicker.class, "lookupStockTicker"))
.build()
);
}
@Schema(
name = "lookup_stock_ticker",
description = "Lookup stock price for a given company or ticker"
)
public static Map<String, String> lookupStockTicker(
@Schema(name = "company_name_or_stock_ticker", description = "The company name or stock ticker")
String ticker) {
// ... (logic to return a stock price)
}
}
এজেন্টদের আরও স্মার্ট করে তুলতে এবং তাদের বিশ্বের সাথে ইন্টারঅ্যাক্ট করার ক্ষমতা দিতে (বা আপনার নিজের কোড, API, পরিষেবা ইত্যাদির সাথে) আপনি এজেন্টকে টুলস ব্যবহার করার জন্য কনফিগার করতে পারেন, এবং বিশেষ করে কাস্টম কোড টুল, tools()
পদ্ধতির মাধ্যমে, এটি একটি FunctionTool.create(...)
পাস করে।
FunctionTool
একটি ক্লাস এবং একটি পদ্ধতির নাম প্রয়োজন যা আপনার নিজস্ব স্ট্যাটিক পদ্ধতির দিকে নির্দেশ করে — এটি একটি ক্লাসের একটি উদাহরণ এবং সেই বস্তুর একটি উদাহরণ পদ্ধতির নাম পাস করাও সম্ভব।
@Schema
টীকা-এর মাধ্যমে উভয় পদ্ধতির name
এবং description
এবং এর পরামিতি উল্লেখ করা গুরুত্বপূর্ণ, কারণ এই তথ্যটি অন্তর্নিহিত LLM দ্বারা ব্যবহৃত হবে যাতে একটি প্রদত্ত পদ্ধতিকে কখন এবং কীভাবে কল করা উচিত।
সমানভাবে গুরুত্বপূর্ণ, কীভাবে এবং কখন টুলটি ব্যবহার করতে হবে সে সম্পর্কে স্পষ্ট নির্দেশাবলী দিয়ে এলএলএম-কে সাহায্য করা ভাল। মডেলটি নিজেরাই এটি বের করতে সক্ষম হতে পারে, কিন্তু আপনি যদি instruction()
পদ্ধতিতে সুস্পষ্ট ব্যাখ্যা দেন, তাহলে আপনার ফাংশনটিকে যথাযথভাবে বলা হওয়ার সম্ভাবনা বেশি থাকে।
এই পদ্ধতিতে একটি Map
ফেরত দেওয়া উচিত। সাধারণত, ধারণাটি হল একটি কী সহ একটি মানচিত্র ফেরত দেওয়া যা ফলাফলের প্রতিনিধিত্ব করে, যেমন stock_price
, এবং স্টক মূল্যের মান এর সাথে যুক্ত করা। অবশেষে, আপনি অপারেশনের সাফল্যের সংকেত দিতে একটি অতিরিক্ত সাফল্য / সত্যিকারের কী জোড়া যোগ করতে পারেন। এবং ত্রুটির ক্ষেত্রে, আপনাকে একটি কী সহ একটি মানচিত্র ফেরত দিতে হবে, উদাহরণস্বরূপ, error
, এবং সংশ্লিষ্ট মানের সাথে ত্রুটি বার্তাটি যুক্ত করুন৷ এটি এলএলএমকে বুঝতে সাহায্য করে যে কলটি সফল হয়েছে বা কোনো কারণে ব্যর্থ হয়েছে কিনা।
- সফল হলে, ফেরত দিন:
{"stock_price": 123}
- ত্রুটি হলে, ফেরত দিন:
{"error": "Impossible to retrieve stock price for XYZ"}
তারপর নিম্নলিখিত কমান্ড দিয়ে এই ক্লাস চালান:
mvn compile exec:java -Dexec.mainClass=com.example.agent.StockTicker
5. আপ-টু-ডেট তথ্যের জন্য Google অনুসন্ধানের শক্তি
জাভার জন্য ADK মুষ্টিমেয় শক্তিশালী টুলের সাথে আসে, যার মধ্যে রয়েছে GoogleSearchTool
. এই টুলের সাহায্যে, আপনার এজেন্ট তার লক্ষ্যে পৌঁছানোর জন্য প্রাসঙ্গিক তথ্য খুঁজে পেতে Google অনুসন্ধান ব্যবহার করার অনুরোধ করতে পারে।
প্রকৃতপক্ষে, একটি এলএলএম-এর জ্ঞান সময়মতো হিমায়িত হয়: এটি একটি নির্দিষ্ট তারিখ ("কাট-অফ ডেট") পর্যন্ত ডেটা সহ প্রশিক্ষণ দেওয়া হয়েছে যা তথ্য সংগ্রহ করার সময় পর্যন্ত আপ-টু-ডেট। এর মানে হল যে এলএলএমগুলি সাম্প্রতিক ঘটনাগুলি সম্পর্কে অগত্যা নাও জানতে পারে, বা তাদের জ্ঞান সীমিত এবং অগভীর হতে পারে এবং একটি সার্চ ইঞ্জিনের সাহায্য তাদের স্মৃতিকে সতেজ করতে পারে বা বিষয়টি সম্পর্কে তাদের আরও শেখাতে পারে।
আসুন এই সাধারণ সংবাদ অনুসন্ধান এজেন্টের দিকে নজর দেওয়া যাক:
// src/main/java/com/example/agent/LatestNews.java
package com.example.agent;
import java.time.LocalDate;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;
public class LatestNews {
public static void main(String[] args) {
AdkWebServer.start(LlmAgent.builder()
.name("news-search-agent")
.description("A news search agent")
.instruction("""
You are a news search agent.
Use the `google_search` tool
when asked to search for recent events and information.
Today is \
""" + LocalDate.now())
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.build());
}
}
লক্ষ্য করুন কিভাবে আমরা সার্চ টুলের একটি উদাহরণ এর সাথে পাস করেছি: tools(new GoogleSearchTool())
। এটিই আমাদের এজেন্টকে ওয়েবে পাওয়া সর্বশেষ তথ্যের সাথে দ্রুত গতিতে যাওয়ার ক্ষমতা দেয়। এছাড়াও, প্রম্পটে দিনের তারিখ উল্লেখ করা হয়েছে, কারণ এটি এলএলএমকে বুঝতে সাহায্য করতে পারে কখন প্রশ্নগুলি অতীতের তথ্য সম্পর্কে এবং আরও সাম্প্রতিক তথ্যের সন্ধানের প্রয়োজন।
তারপর নিম্নলিখিত কমান্ড দিয়ে এই ক্লাস চালান:
mvn compile exec:java -Dexec.mainClass=com.example.agent.LatestNews
প্রম্পটের সাথে খেলতে নির্দ্বিধায়, শৈলী, সংক্ষিপ্ততা বা ফোকাস ইত্যাদির ক্ষেত্রে বিভিন্ন ফলাফলের জন্য জিজ্ঞাসা করুন।
কোড ধাপ: একটি টুল হিসাবে অনুসন্ধান এজেন্ট
GoogleSearchTool
একটি টুল হিসাবে সরাসরি একটি এজেন্টের কাছে পাঠানোর পরিবর্তে, আপনি একটি ডেডিকেটেড সার্চ এজেন্ট তৈরি করতে পারেন যা সার্চ কার্যকারিতাকে এনক্যাপসুলেট করে এবং সেই এজেন্টটিকে একটি উচ্চ-স্তরের এজেন্টের কাছে একটি টুল হিসাবে প্রকাশ করে৷
এটি একটি উন্নত ধারণা যা আপনাকে একটি বিশেষ উপ-এজেন্টকে জটিল আচরণ (যেমন অনুসন্ধান এবং ফলাফলের সংক্ষিপ্তকরণ) অর্পণ করতে দেয়। এই পদ্ধতিটি প্রায়শই আরও জটিল কর্মপ্রবাহের জন্য উপযোগী, কারণ অন্তর্নির্মিত সরঞ্জামগুলি কাস্টম কোড-ভিত্তিক সরঞ্জামগুলির সাথে ব্যবহার করা যায় না।
// src/main/java/com/example/agent/SearchAgentAsTool.java
package com.example.agent;
import java.time.LocalDate;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.AgentTool;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;
public class SearchAgentAsTool {
public static void main(String[] args) {
// 1. Define the specialized Search Agent
LlmAgent searchAgent = LlmAgent.builder()
.name("news-search-agent-tool")
.description("Searches for recent events and provides a concise summary.")
.instruction("""
You are a concise information retrieval specialist.
Use the `google_search` tool to find information.
Always provide the answer as a short,
direct summary, without commentary.
Today is \
""" + LocalDate.now())
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool()) // This agent uses the Google Search Tool
.build();
// 2. Wrap the Search Agent as a Tool
AgentTool searchTool = AgentTool.create(searchAgent);
// 3. Define the Main Agent that uses the Search Agent Tool
AdkWebServer.start(LlmAgent.builder()
.name("main-researcher")
.description("Main agent for answering complex, up-to-date questions.")
.instruction("""
You are a sophisticated research assistant.
When the user asks a question that requires up-to-date or external information,
you MUST use the `news-search-agent-tool` to get the facts before answering.
After the tool returns the result, synthesize the final answer for the user.
""")
.model("gemini-2.5-flash")
.tools(searchTool) // This agent uses the Search Agent as a tool
.build()
);
}
}
AgentTool.create(searchAgent)
লাইনটি এখানে মূল ধারণা। এটি mainAgent
জন্য একটি একক কলযোগ্য টুল হিসাবে সমগ্র searchAgent
(এর নিজস্ব অভ্যন্তরীণ যুক্তি, প্রম্পট এবং সরঞ্জাম সহ) নিবন্ধন করে। এটি মডুলারিটি এবং পুনরায় ব্যবহারযোগ্যতা প্রচার করে।
নিম্নলিখিত কমান্ড দিয়ে এই ক্লাস চালান:
mvn compile exec:java -Dexec.mainClass=com.example.agent.SearchAgentAsTool
জাগতিক প্রশ্নের জন্য, এজেন্ট তার নিজস্ব জ্ঞানের ভিত্তি থেকে উত্তর দেবে, কিন্তু সাম্প্রতিক ঘটনা সম্পর্কে জিজ্ঞাসা করা হলে, এটি Google অনুসন্ধান টুল ব্যবহার করে বিশেষ অনুসন্ধান এজেন্টকে অনুসন্ধান অর্পণ করবে।
6. এজেন্টিক ওয়ার্কফ্লো আয়ত্ত করা
জটিল সমস্যার জন্য, একটি একক এজেন্ট যথেষ্ট নয়। যখন একটি লক্ষ্য দেওয়া হয় যা অনেকগুলি সাব-টাস্ক নিয়ে গঠিত, একটি বিশাল প্রম্পট অত্যধিক বিশদ ব্যাখ্যা সহ, বা বিপুল সংখ্যক ফাংশনে অ্যাক্সেস সহ, এলএলএমগুলি লড়াই করে এবং তাদের কার্যকারিতা এবং নির্ভুলতা হ্রাস পায়।
মূল বিষয় হল একাধিক বিশেষায়িত এজেন্টদের অর্কেস্ট্রেট করে ভাগ করা এবং জয় করা । সৌভাগ্যবশত, ADK বিভিন্ন বিল্ট-ইন বিশেষায়িত এজেন্টের সাথে আসে:
-
subAgent()
এর সাথে সাধারণ এজেন্টকে কাজ অর্পণ করতে, -
SequentialAgent
, একটি ক্রমানুসারে কাজগুলি করতে, -
ParallelAgent
, সমান্তরালে এজেন্ট চালানোর জন্য, -
LoopAgent
, সাধারণত যতবার প্রয়োজন ততবার পরিমার্জন প্রক্রিয়ার মধ্য দিয়ে যাওয়ার জন্য।
মূল ব্যবহারের ক্ষেত্রে কী কী, এবং প্রতিটি কর্মপ্রবাহের সুবিধা এবং অসুবিধাগুলি, দয়া করে নীচের সারণীটি দেখুন৷ কিন্তু জেনে রাখুন আসল ক্ষমতা আসলে আসবে তাদের বেশ কয়েকটির সমন্বয় থেকে!
কর্মপ্রবাহ | এডিকে ক্লাস | কেস ব্যবহার করুন | পেশাদার | কনস |
সাব-এজেন্ট | | ব্যবহারকারী-চালিত, নমনীয় কাজ যেখানে পরবর্তী পদক্ষেপ সবসময় জানা যায় না। | উচ্চ নমনীয়তা, কথোপকথন, ব্যবহারকারী-মুখী বটগুলির জন্য দুর্দান্ত। | কম অনুমানযোগ্য, প্রবাহ নিয়ন্ত্রণের জন্য LLM যুক্তির উপর নির্ভর করে। |
অনুক্রমিক | | স্থির, বহু-পদক্ষেপের প্রক্রিয়া যেখানে অর্ডার গুরুত্বপূর্ণ। | অনুমানযোগ্য, নির্ভরযোগ্য, ডিবাগ করা সহজ, অর্ডারের নিশ্চয়তা দেয়। | অনমনীয়, ধীর হতে পারে যদি কাজগুলি সমান্তরাল করা যায়। |
সমান্তরাল | | একাধিক উত্স থেকে ডেটা সংগ্রহ করা বা স্বাধীন কাজ চালানো। | অত্যন্ত দক্ষ, উল্লেখযোগ্যভাবে I/O- আবদ্ধ কাজগুলির জন্য বিলম্ব কমায়৷ | সমস্ত কাজ সঞ্চালিত হয়; কোন শর্ট সার্কিটিং নির্ভরতা সহ কাজের জন্য কম উপযুক্ত। |
লুপ | | পুনরাবৃত্তিমূলক পরিমার্জন, স্ব-সংশোধন, বা প্রসেস যা একটি শর্ত পূরণ না হওয়া পর্যন্ত পুনরাবৃত্তি হয়। | জটিল সমস্যা সমাধানের জন্য শক্তিশালী, এজেন্টদের তাদের নিজস্ব কাজ উন্নত করতে সক্ষম করে। | সাবধানে ডিজাইন না করা হলে অসীম লুপ হতে পারে (সর্বদা maxIterations ব্যবহার করুন!) |
7. এজেন্টিক কর্মপ্রবাহ — সাব-এজেন্টদের সাথে প্রতিনিধি দল
একজন সুপারভাইজার এজেন্ট সাব-এজেন্টদের নির্দিষ্ট কাজ অর্পণ করতে পারেন। উদাহরণস্বরূপ, একটি ই-কমার্স ওয়েবসাইটের এজেন্টকে কল্পনা করুন যেটি একটি এজেন্টকে অর্ডার সম্পর্কিত প্রশ্ন অর্পণ করবে ("আমার অর্ডারের অবস্থা কী?") এবং বিক্রয়োত্তর পরিষেবার প্রশ্নগুলি অন্য এজেন্টকে দেবে ("আমি জানি না কিভাবে এটি চালু করতে হয়!")। এই ব্যবহার কেস আমরা আলোচনা করতে যাচ্ছি.
// src/main/java/com/example/agent/SupportAgent.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.web.AdkWebServer;
public class SupportAgent {
public static void main(String[] args) {
LlmAgent topicSearchAgent = LlmAgent.builder()
.name("order-agent")
.description("Order agent")
.instruction("""
Your role is to help our customers
with all the questions they may have about their orders.
Always respond that the order has been received, prepared,
and is now out for delivery.
""")
.model("gemini-2.5-flash")
.build();
LlmAgent socialMediaAgent = LlmAgent.builder()
.name("after-sale-agent")
.description("After sale agent")
.instruction("""
You are an after sale agent,
helping customers with the product they received.
When a customer has a problem,
suggest the person to switch the product off and on again.
""")
.model("gemini-2.5-flash")
.build();
AdkWebServer.start(LlmAgent.builder()
.name("support-agent")
.description("Customer support agent")
.instruction("""
Your role is help our customers.
Call the `order-agent` for all questions related to order status.
Call the `after-sale-agent` for inquiries about the received product.
""")
.model("gemini-2.5-flash")
.subAgents(socialMediaAgent, topicSearchAgent)
.build()
);
}
}
এখানে মূল লাইনটি হল যেখানে subAgents()
পদ্ধতি বলা হয়, দুটি সাব-এজেন্টের মধ্যে পাস করে যাদের নির্দিষ্ট ভূমিকা একে অপরের দ্বারা পৃথকভাবে পরিচালনা করা হবে।
নিম্নলিখিত কমান্ড দিয়ে উপরের উদাহরণটি চালান:
mvn compile exec:java -Dexec.mainClass=com.example.agent.SupportAgent
সাব-এজেন্টদের কাছে কাজগুলি অর্পণ করার এই ধারণাটি কার্যকর মানব ব্যবস্থাপনার প্রতিফলন করে, যেখানে একজন ভাল ব্যবস্থাপক (তত্ত্বাবধায়ক এজেন্ট) নির্দিষ্ট কাজগুলি পরিচালনা করার জন্য বিশেষ কর্মচারীদের (সাব-এজেন্ট) উপর নির্ভর করে যার জন্য তাদের বেশি দক্ষতা রয়েছে। সুপারভাইজারকে প্রতিটি প্রক্রিয়ার বিবরণ জানার প্রয়োজন নেই; পরিবর্তে, এটি বুদ্ধিমানের সাথে একজন গ্রাহকের অনুরোধ (যেমন একটি অর্ডার অনুসন্ধান বা প্রযুক্তিগত সমস্যা) সবচেয়ে যোগ্য 'টিম সদস্য'-এর কাছে প্রেরণ করে, যা একজন সাধারণ বিশেষজ্ঞ একাই প্রদান করতে পারে তার চেয়ে উচ্চ মানের এবং আরও দক্ষ প্রতিক্রিয়া নিশ্চিত করে। তদ্ব্যতীত, এই সাব-এজেন্টরা জটিল ওভারআর্চিং প্রক্রিয়ার সম্পূর্ণতা বোঝার প্রয়োজন ছাড়াই তাদের পৃথক অ্যাসাইনমেন্টে সম্পূর্ণরূপে মনোনিবেশ করতে পারে।
8. এজেন্টিক কর্মপ্রবাহ — সমাবেশ লাইন
যখন অপারেশনের ক্রম গুরুত্বপূর্ণ, একটি SequentialAgent
ব্যবহার করুন। এটি একটি অ্যাসেম্বলি লাইনের মতো, একটি নির্দিষ্ট ক্রমে সাব-এজেন্ট নির্বাহ করে যেখানে প্রতিটি পদক্ষেপ পূর্ববর্তীটির উপর নির্ভর করতে পারে।
আসুন কল্পনা করি একজন ইংরেজ কবি একজন ইংরেজ-ফরাসি অনুবাদকের সাথে সহযোগিতা করে প্রথমে ইংরেজিতে কবিতা তৈরি করেন এবং তারপরে সেগুলিকে ফরাসি ভাষায় অনুবাদ করেন:
// src/main/java/com/example/agent/PoetAndTranslator.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.web.AdkWebServer;
public class PoetAndTranslator {
public static void main(String[] args) {
LlmAgent poet = LlmAgent.builder()
.name("poet-agent")
.description("Poet writing poems")
.model("gemini-2.5-flash")
.instruction("""
You are a talented poet,
who writes short and beautiful poems.
""")
.outputKey("poem")
.build();
LlmAgent translator = LlmAgent.builder()
.name("translator-agent")
.description("English to French translator")
.model("gemini-2.5-flash")
.instruction("""
As an expert English-French translator,
your role is to translate the following poem into French,
ensuring the poem still rhymes even after translation:
{poem}
""")
.outputKey("translated-poem")
.build();
AdkWebServer.start(SequentialAgent.builder()
.name("poet-and-translator")
.subAgents(poet, translator)
.build());
}
}
ইংরেজিতে একটি কবিতা পেতে উদাহরণটি চালান, তারপরে নিম্নলিখিত কমান্ড সহ ফরাসি ভাষায় অনুবাদ করুন:
mvn compile exec:java -Dexec.mainClass=com.example.agent.PoetAndTranslator
জটিল কাজগুলিকে ছোট, অর্ডার করা সাব-টাস্কগুলিতে এই পদ্ধতিগতভাবে পচন একটি আরও নির্ণায়ক এবং নির্ভরযোগ্য প্রক্রিয়া নিশ্চিত করে, একটি একক, ব্যাপকভাবে উদ্দেশ্যমূলক এজেন্টের উপর নির্ভর করার তুলনায় একটি সফল ফলাফলের সম্ভাবনা উল্লেখযোগ্যভাবে বৃদ্ধি করে।
কার্যকরভাবে একটি কাজকে উপ-টাস্কের একটি ক্রম (যখন সম্ভব এবং যখন এটি বোধগম্য হয়) মধ্যে বিভক্ত করা আরও নির্ধারক এবং সফল ফলাফল অর্জনের জন্য অত্যন্ত গুরুত্বপূর্ণ, কারণ এটি ধাপগুলির মধ্যে কাঠামোগত অগ্রগতি এবং নির্ভরতা ব্যবস্থাপনার অনুমতি দেয়।
9. এজেন্টিক ওয়ার্কফ্লোস — সমান্তরালভাবে কাজ করা
যখন কাজগুলি স্বাধীন হয়, তখন একটি ParallelAgent
একই সাথে চালানোর মাধ্যমে একটি বিশাল দক্ষতা বৃদ্ধি করে। নিম্নলিখিত উদাহরণে, আমরা একটি ParallelAgent
এজেন্টের সাথে একটি SequentialAgent
একত্রিত করব : সমান্তরাল কাজগুলি প্রথমে চলে, এবং তারপর একটি চূড়ান্ত এজেন্ট সমান্তরাল কার্যগুলির ফলাফলের সংক্ষিপ্তসার করে৷
আসুন একটি কোম্পানি গোয়েন্দা তৈরি করি যার কাজ হবে তথ্য অনুসন্ধান করা:
- কোম্পানির প্রোফাইল (সিইও, সদর দপ্তর, নীতিবাক্য, ইত্যাদি)
- কোম্পানি সম্পর্কে সর্বশেষ খবর.
- কোম্পানির আর্থিক সম্পর্কে বিস্তারিত.
// src/main/java/com/example/agent/CompanyDetective.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.ParallelAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;
public class CompanyDetective {
public static void main(String[] args) {
var companyProfiler = LlmAgent.builder()
.name("company-profiler")
.description("Provides a general overview of a company.")
.instruction("""
Your role is to provide a brief overview of the given company.
Include its mission, headquarters, and current CEO.
Use the Google Search Tool to find this information.
""")
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.outputKey("profile")
.build();
var newsFinder = LlmAgent.builder()
.name("news-finder")
.description("Finds the latest news about a company.")
.instruction("""
Your role is to find the top 3-4 recent news headlines for the given company.
Use the Google Search Tool.
Present the results as a simple bulleted list.
""")
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.outputKey("news")
.build();
var financialAnalyst = LlmAgent.builder()
.name("financial-analyst")
.description("Analyzes the financial performance of a company.")
.instruction("""
Your role is to provide a snapshot of the given company's recent financial performance.
Focus on stock trends or recent earnings reports.
Use the Google Search Tool.
""")
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.outputKey("financials")
.build();
var marketResearcher = ParallelAgent.builder()
.name("market-researcher")
.description("Performs comprehensive market research on a company.")
.subAgents(
companyProfiler,
newsFinder,
financialAnalyst
)
.build();
var reportCompiler = LlmAgent.builder()
.name("report-compiler")
.description("Compiles a final market research report.")
.instruction("""
Your role is to synthesize the provided information into a coherent market research report.
Combine the company profile, latest news, and financial analysis into a single, well-formatted report.
## Company Profile
{profile}
## Latest News
{news}
## Financial Snapshot
{financials}
""")
.model("gemini-2.5-flash")
.build();
AdkWebServer.start(SequentialAgent.builder()
.name("company-detective")
.description("Collects various information about a company.")
.subAgents(
marketResearcher,
reportCompiler
).build());
}
}
যথারীতি, আপনি নিম্নলিখিত কমান্ড দিয়ে এজেন্ট চালাতে পারেন:
mvn compile exec:java -Dexec.mainClass=com.example.agent.CompanyDetective
তথ্য গবেষণা এবং সংশ্লেষণের সমান্তরালকরণের জন্য এই এজেন্টটি কার্যপ্রবাহের একটি শক্তিশালী সংমিশ্রণ প্রদর্শন করে, সমান্তরাল এবং অনুক্রমিক উভয় এজেন্টকে ভালো ব্যবহার করা হয়।
10. এজেন্টিক কর্মপ্রবাহ — পুনরাবৃত্তিমূলক পরিমার্জন
একটি "জেনারেট → রিভিউ → রিফাইন" চক্রের প্রয়োজনের জন্য, একটি LoopAgent
ব্যবহার করুন৷ একটি লক্ষ্য পূরণ না হওয়া পর্যন্ত এটি পুনরাবৃত্তিমূলক উন্নতি স্বয়ংক্রিয় করে। একইভাবে SequentialAgent
, LoopAgent
সাব-এজেন্টকে ক্রমিকভাবে কল করবে, কিন্তু এটি শুরুতে লুপ ব্যাক করবে। এটি এজেন্ট দ্বারা অভ্যন্তরীণভাবে ব্যবহৃত এলএলএম যা লুপটি কার্যকর করা বন্ধ করার জন্য একটি বিশেষ টুল, exit_loop
বিল্ট-ইন টুলে কল করার অনুরোধ করবে কিনা তা সিদ্ধান্ত নেবে।
নীচের কোড রিফাইনার উদাহরণ, একটি LoopAgent
ব্যবহার করে, কোড পরিমার্জন স্বয়ংক্রিয় করে: জেনারেট, পর্যালোচনা, সঠিক। এটি মানুষের বিকাশকে অনুকরণ করে। একটি কোড জেনারেটর প্রথমে অনুরোধ করা কোড তৈরি করে, এটিকে generated_code
কী-এর অধীনে এজেন্ট অবস্থায় সংরক্ষণ করে। একটি কোড পর্যালোচক তারপর জেনারেট করা কোড পর্যালোচনা করে, এবং হয় প্রতিক্রিয়া প্রদান করে ( feedback
কী-এর অধীনে), অথবা পুনরুক্তিটি তাড়াতাড়ি শেষ করতে একটি এক্সিট লুপ টুল কল করে।
আসুন কোডটি দেখে নেওয়া যাক:
// src/main/java/com/example/agent/CodeRefiner.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.LoopAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.tools.ExitLoopTool;
import com.google.adk.web.AdkWebServer;
public class CodeRefiner {
public static void main(String[] args) {
var codeGenerator = LlmAgent.builder()
.name("code-generator")
.description("Writes and refines code based on a request and feedback.")
.instruction("""
Your role is to write a Python function based on the user's request.
In the first turn, write the initial version of the code.
In subsequent turns, you will receive feedback on your code.
Your task is to refine the code based on this feedback.
Previous feedback (if any):
{feedback?}
""")
.model("gemini-2.5-flash")
.outputKey("generated_code")
.build();
var codeReviewer = LlmAgent.builder()
.name("code-reviewer")
.description("Reviews code and decides if it's complete or needs more work.")
.instruction("""
Your role is to act as a senior code reviewer.
Analyze the provided Python code for correctness, style, and potential bugs.
Code to review:
{generated_code}
If the code is perfect and meets the user's request,
you MUST call the `exit_loop` tool.
Otherwise, provide constructive feedback for the `code-generator to improve the code.
""")
.model("gemini-2.5-flash")
.outputKey("feedback")
.tools(ExitLoopTool.INSTANCE)
.build();
var codeRefinerLoop = LoopAgent.builder()
.name("code-refiner-loop")
.description("Iteratively generates and reviews code until it is correct.")
.subAgents(
codeGenerator,
codeReviewer
)
.maxIterations(3) // Safety net to prevent infinite loops
.build();
var finalPresenter = LlmAgent.builder()
.name("final-presenter")
.description("Presents the final, accepted code to the user.")
.instruction("""
The code has been successfully generated and reviewed.
Present the final version of the code to the user in a clear format.
Final Code:
{generated_code}
""")
.model("gemini-2.5-flash")
.build();
AdkWebServer.start(SequentialAgent.builder()
.name("code-refiner-assistant")
.description("Manages the full code generation and refinement process.")
.subAgents(
codeRefinerLoop,
finalPresenter)
.build());
}
}
নিম্নলিখিত কমান্ড দিয়ে এই এজেন্ট চালান:
mvn compile exec:java -Dexec.mainClass=com.example.agent.CodeRefiner
LoopAgent
ব্যবহার করে বাস্তবায়িত ফিডব্যাক/পরিমার্জিত লুপগুলি মানুষের জ্ঞানীয় প্রক্রিয়াগুলিকে ঘনিষ্ঠভাবে অনুকরণ করে, পুনরাবৃত্তিমূলক উন্নতি এবং স্ব-সংশোধনের প্রয়োজন এমন সমস্যার সমাধানের জন্য অপরিহার্য। এই ডিজাইন প্যাটার্নটি বিশেষভাবে সেই কাজের জন্য উপযোগী যেখানে প্রাথমিক আউটপুট খুব কমই নিখুঁত হয়, যেমন কোড তৈরি, সৃজনশীল লেখা, নকশা পুনরাবৃত্তি, বা জটিল ডেটা বিশ্লেষণ। কাঠামোগত প্রতিক্রিয়া প্রদান করে এমন একটি বিশেষ পর্যালোচক এজেন্টের মাধ্যমে আউটপুট সাইকেল চালানোর মাধ্যমে, জেনারেটিং এজেন্ট একটি পূর্বনির্ধারিত সমাপ্তির মাপকাঠি পূরণ না হওয়া পর্যন্ত তার কাজকে ক্রমাগত পরিমার্জন করতে পারে, যা একক-পাস পদ্ধতির চেয়ে প্রদর্শনযোগ্যভাবে উচ্চ মানের এবং আরও নির্ভরযোগ্য চূড়ান্ত ফলাফলের দিকে পরিচালিত করে।
11. অভিনন্দন!
সাধারণ কথোপকথনবাদী থেকে জটিল, মাল্টি-এজেন্ট সিস্টেম পর্যন্ত আপনি সফলভাবে বিভিন্ন ধরনের এআই এজেন্ট তৈরি এবং অন্বেষণ করেছেন। আপনি জাভার জন্য ADK-এর মূল ধারণাগুলি শিখেছেন: নির্দেশাবলীর সাহায্যে এজেন্টদের সংজ্ঞায়িত করা, তাদের টুলের সাহায্যে ক্ষমতায়ন করা এবং শক্তিশালী কর্মপ্রবাহে তাদের অর্কেস্ট্রেট করা।
এরপর কি?
- Java GitHub সংগ্রহস্থলের জন্য অফিসিয়াল ADK অন্বেষণ করুন।
- এর ডকুমেন্টেশনে ফ্রেমওয়ার্ক সম্পর্কে আরও জানুন।
- এই ব্লগ সিরিজের বিভিন্ন এজেন্টিক কর্মপ্রবাহ এবং উপলব্ধ বিভিন্ন সরঞ্জাম সম্পর্কে পড়ুন।
- অন্যান্য অন্তর্নির্মিত সরঞ্জাম এবং উন্নত কলব্যাকগুলির মধ্যে আরও গভীরে যান৷
- আরও সমৃদ্ধ এবং বহুমুখী মিথস্ক্রিয়াগুলির জন্য প্রসঙ্গ, রাজ্য এবং শিল্পকর্মগুলি পরিচালনা করুন।
- আপনার এজেন্টদের জীবনচক্রে প্লাগইন করে এমন প্লাগইনগুলি প্রয়োগ করুন এবং প্রয়োগ করুন৷
- আপনার নিজস্ব এজেন্ট তৈরি করার চেষ্টা করুন যা একটি বাস্তব-বিশ্বের সমস্যা সমাধান করে!
1. স্বাগতম, এআই এজেন্ট ডেভেলপার!
এই কোডল্যাবে, আপনি জাভা-এর জন্য এজেন্ট ডেভেলপমেন্ট কিট (ADK) ব্যবহার করে জাভাতে AI এজেন্ট কীভাবে তৈরি করবেন তা শিখবেন। আমরা সহজ লার্জ ল্যাঙ্গুয়েজ মডেল (LLM) API কলের বাইরে চলে যাব স্বায়ত্তশাসিত AI এজেন্ট তৈরি করতে যা যুক্তি দিতে পারে, পরিকল্পনা করতে পারে, টুল ব্যবহার করতে পারে এবং জটিল সমস্যার সমাধান করতে একসঙ্গে কাজ করতে পারে।
আপনি Google ক্লাউড ক্রেডিটগুলি রিডিম করে শুরু করবেন, আপনার Google ক্লাউড পরিবেশ সেট আপ করবেন, তারপর আপনার প্রথম সাধারণ এজেন্ট তৈরি করবেন এবং ক্রমান্বয়ে কাস্টম টুল, ওয়েব অনুসন্ধান এবং মাল্টি-এজেন্ট অর্কেস্ট্রেশনের মতো আরও উন্নত ক্ষমতা যুক্ত করবেন৷
আপনি কি শিখবেন
- কীভাবে একটি মৌলিক, ব্যক্তি-চালিত এআই এজেন্ট তৈরি করবেন।
- কাস্টম এবং বিল্ট-ইন টুল (যেমন Google অনুসন্ধান) দিয়ে এজেন্টকে কীভাবে ক্ষমতায়ন করা যায়।
- জাভাতে বাস্তবায়িত আপনার নিজস্ব সরঞ্জামগুলি কীভাবে যুক্ত করবেন।
- কিভাবে একাধিক এজেন্টকে শক্তিশালী অনুক্রমিক, সমান্তরাল এবং লুপিং ওয়ার্কফ্লোতে অর্কেস্ট্রেট করা যায়।
আপনি কি প্রয়োজন হবে
- একটি ওয়েব ব্রাউজার যা আমরা ছদ্মবেশী মোডে ব্যবহার করব।
- একটি ব্যক্তিগত জিমেইল অ্যাকাউন্ট।
- আপনার ব্যক্তিগত Gmail অ্যাকাউন্টের সাথে যুক্ত একটি নতুন Google ক্লাউড প্রকল্প৷
- রিডিম করা Google ক্লাউড ক্রেডিট দিয়ে একটি বিলিং অ্যাকাউন্ট তৈরি করা হয়েছে।
- সোর্স কোড পরীক্ষা করার জন্য গিট কমান্ড-লাইন টুল।
- Java 17+ এবং Apache Maven।
- একটি পাঠ্য সম্পাদক বা IDE, যেমন IntelliJ IDEA বা VS কোড।
Google ক্লাউড কনসোলে ক্লাউড শেল-এ অন্তর্নির্মিত VS কোড সম্পাদক ব্যবহার করা সম্ভব।
2. সেটআপ: আপনার পরিবেশ
ওয়ার্কশপের জন্য Google ক্লাউড ক্রেডিট দাবি করা
একটি প্রশিক্ষকের নেতৃত্বে কর্মশালার জন্য, আপনি ওয়েবসাইটের একটি লিঙ্ক পাবেন যেখানে আপনি কর্মশালার জন্য ব্যবহার করার জন্য Google ক্লাউড ক্রেডিট দাবি করতে পারেন।
- একটি ব্যক্তিগত Google অ্যাকাউন্ট ব্যবহার করুন : কর্পোরেট বা স্কুল ইমেল ঠিকানাগুলি কাজ করবে না বলে একটি ব্যক্তিগত Google অ্যাকাউন্ট (যেমন একটি gmail.com ঠিকানা) ব্যবহার করা গুরুত্বপূর্ণ।
- ছদ্মবেশী মোডে Google Chrome ব্যবহার করুন : এটি একটি পরিষ্কার সেশন তৈরি করতে এবং অন্যান্য Google অ্যাকাউন্টগুলির সাথে দ্বন্দ্ব প্রতিরোধ করার জন্য সুপারিশ করা হয়৷
- বিশেষ ইভেন্ট লিঙ্ক ব্যবহার করুন : ইভেন্টের জন্য একটি বিশেষ লিঙ্ক, যা দেখতে https://trygcp.dev/event/xxx এর মতো একটি ইভেন্ট কোড (এই উদাহরণে এখানে "xxx") ব্যবহার করা উচিত।
- পরিষেবার শর্তাদি স্বীকার করুন : সাইন ইন করার পরে, আপনাকে Google ক্লাউড প্ল্যাটফর্মের পরিষেবার শর্তাবলী উপস্থাপন করা হবে, যা চালিয়ে যেতে আপনাকে স্বীকার করতে হবে৷
- একটি নতুন প্রকল্প তৈরি করুন : Google ক্লাউড কনসোল থেকে একটি নতুন খালি প্রকল্প তৈরি করতে হবে৷
- একটি বিলিং অ্যাকাউন্ট লিঙ্ক করুন : একটি বিলিং অ্যাকাউন্টের সাথে নতুন তৈরি প্রকল্প লিঙ্ক করুন।
- ক্রেডিট নিশ্চিত করুন : নিম্নলিখিত ভিডিওটি বিলিং পৃষ্ঠায় "ক্রেডিট" বিভাগটি চেক করে কীভাবে প্রকল্পে ক্রেডিট প্রয়োগ করা হয়েছে তা নিশ্চিত করতে দেখায়।
নির্দ্বিধায় এই ভিডিওটি দেখুন যা ব্যাখ্যা করে যে কীভাবে ক্রেডিটগুলি রিডিম করা যায় এবং প্রয়োগ করা যায়৷
আপনার API কী তৈরি করুন এবং কনফিগার করুন
এই কোডল্যাবের জন্য Gemini API-এর সাথে আপনার ADK AI এজেন্টদের প্রমাণীকরণ করতে, আপনি আপনার Google ক্লাউড প্রকল্পের সাথে যুক্ত একটি API কী ব্যবহার করবেন।
- একটি API কী তৈরি করুন:
- গুগল এআই স্টুডিওতে যান এবং বাম পাশের প্যানেলের নীচে "এপিআই কী পান" লিঙ্কটিতে ক্লিক করুন।
- প্রকল্পগুলি নির্বাচন করুন এবং তারপরে আমদানি প্রকল্প বোতামে ক্লিক করুন।
- আপনি যে Google ক্লাউড প্রকল্পটি আমদানি করতে চান সেটি অনুসন্ধান করুন এবং নির্বাচন করুন , তারপর আমদানি বোতামটি নির্বাচন করুন৷
- একবার প্রজেক্ট ইম্পোর্ট করা হয়ে গেলে, ড্যাশবোর্ড মেনু থেকে API কী পৃষ্ঠায় যান এবং আপনি এইমাত্র যে প্রোজেক্টটি আমদানি করেছেন তাতে একটি API কী তৈরি করুন।
- API কী নোট করুন ।
- এনভায়রনমেন্ট ভেরিয়েবল সেট করুন: আপনার এজেন্টকে এই কী অ্যাক্সেস করতে হবে। আদর্শ উপায় হল
GOOGLE_API_KEY
নামের একটি পরিবেশ পরিবর্তনশীল সেট করা।
- macOS / Linux: আপনার টার্মিনাল খুলুন এবং
"your-api-key"
প্রতিস্থাপন করে নিম্নলিখিত কমান্ডটি চালান যা আপনি এইমাত্র কপি করেছেন। এটিকে স্থায়ী করতে, আপনার শেলের স্টার্টআপ ফাইলে এই লাইনটি যোগ করুন (যেমন,~/.bash_profile
,~/.zshrc
)।
export GOOGLE_API_KEY="your-api-key"
- উইন্ডোজ (কমান্ড প্রম্পট): একটি নতুন কমান্ড প্রম্পট খুলুন এবং চালান:
setx GOOGLE_API_KEY "your-api-key"
- এই পরিবর্তন কার্যকর করার জন্য আপনাকে আপনার কমান্ড প্রম্পট পুনরায় চালু করতে হবে।
- উইন্ডোজ (পাওয়ারশেল): একটি পাওয়ারশেল টার্মিনাল খুলুন এবং চালান:
$env:GOOGLE_API_KEY="your-api-key"
- PowerShell-এ এই পরিবর্তনটি স্থায়ী করতে, আপনাকে এটি আপনার প্রোফাইল স্ক্রিপ্টে যোগ করতে হবে।
3. শুরু করা: আপনার প্রথম এজেন্ট
একটি নতুন প্রকল্প শুরু করার সর্বোত্তম উপায় হল Java GitHub টেমপ্লেটের জন্য ADK ব্যবহার করা। এটি প্রকল্পের কাঠামো এবং সমস্ত প্রয়োজনীয় নির্ভরতা প্রদান করে।
আপনার যদি একটি Github অ্যাকাউন্ট থাকে, আপনি নিম্নলিখিতগুলি করতে পারেন: Use this template
> Create a new repository
, তারপর git clone
কমান্ড দিয়ে স্থানীয়ভাবে কোডটি চেকআউট করুন।
এখানে টেমপ্লেট ব্যবহার করার জন্য উপরের-ডান মেনু দেখানো একটি স্ক্রিনশট।
অন্য পদ্ধতিটি হল সেই সংগ্রহস্থলটি সরাসরি ক্লোন করা, এর সাথে:
git clone https://github.com/glaforge/adk-java-maven-template.git
তারপর adk-java-maven-template
cd
।
আপনি জাভাতে আপনার প্রথম এআই এজেন্ট কোডিং শুরু করতে প্রস্তুত কিনা তা পরীক্ষা করতে, নিশ্চিত করুন যে আপনি এই প্রকল্পে কোডটি এর সাথে কম্পাইল করতে পারেন:
mvn compile
কোড ধাপ: একটি বন্ধুত্বপূর্ণ বিজ্ঞান শিক্ষক এজেন্ট
ADK-এর মৌলিক বিল্ডিং ব্লক হল LlmAgent
ক্লাস। একটি বৃহৎ ভাষার মডেল দ্বারা চালিত একটি নির্দিষ্ট ব্যক্তিত্ব এবং লক্ষ্য সহ একটি AI হিসাবে এটিকে ভাবুন৷ আমরা পরে সরঞ্জামগুলির মাধ্যমে আরও ক্ষমতা যুক্ত করব এবং অন্যান্য অনুরূপ এজেন্টদের সাথে হাতে হাত মিলিয়ে এটিকে আরও শক্তিশালী করে তুলব।
আসুন com.example.agent
প্যাকেজে একটি নতুন জাভা ক্লাস তৈরি করি এবং এটিকে ScienceTeacher
বলি।
এই "হ্যালো, বিশ্ব!" এজেন্ট সৃষ্টির। আমরা একজন বিজ্ঞান শিক্ষকের ব্যক্তিত্বের সাথে একটি সাধারণ এজেন্টকে সংজ্ঞায়িত করছি।
// src/main/java/com/example/agent/ScienceTeacher.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.web.AdkWebServer;
public class ScienceTeacher {
public static void main(String[] args) {
AdkWebServer.start(
LlmAgent.builder()
.name("science-teacher")
.description("A friendly science teacher")
.instruction("""
You are a science teacher for teenagers.
You explain science concepts in a simple, concise and direct way.
""")
.model("gemini-2.5-flash")
.build()
);
}
}
AI এজেন্ট LlmAgent.builder()
পদ্ধতির মাধ্যমে কনফিগার করা হয়েছে। name()
, description()
, এবং model()
প্যারামিটারগুলি বাধ্যতামূলক, এবং আপনার এজেন্টকে একটি নির্দিষ্ট ব্যক্তিত্ব এবং সঠিক আচরণ দিতে, আপনাকে সর্বদা instruction()
পদ্ধতির মাধ্যমে বিস্তারিত নির্দেশনা দিতে হবে।
এখানে আমরা জেমিনি 2.5 ফ্ল্যাশ মডেল ব্যবহার করতে বেছে নিয়েছি, তবে আরও জটিল কাজের জন্য জেমিনি 2.5 প্রো ব্যবহার করে দেখতে নির্দ্বিধায়।
এই এজেন্টটি AdkWebServer.start()
পদ্ধতির মধ্যে মোড়ানো হয়। এটি তথাকথিত ADK Dev UI চ্যাট ইন্টারফেস। এটি আপনাকে একটি সাধারণ চ্যাট ইন্টারফেসের মাধ্যমে এজেন্টের সাথে কথোপকথন করতে দেয়। তদ্ব্যতীত, আপনি যদি বুঝতে চান যে হুডের নীচে কী ঘটছে, যেমন সমস্ত ইভেন্ট যা সিস্টেমের মধ্য দিয়ে প্রবাহিত হচ্ছে, এলএলএম-এ পাঠানো অনুরোধ এবং প্রতিক্রিয়া।
স্থানীয়ভাবে এই এজেন্টটি কম্পাইল এবং চালাতে, নিম্নলিখিত কমান্ডটি চালান:
mvn compile exec:java -Dexec.mainClass=com.example.agent.ScienceTeacher
তারপর http://localhost:8080 এ আপনার ব্রাউজারে যান। নীচের স্ক্রিনশটে দেখানো হিসাবে আপনার UI দেখতে হবে। এগিয়ে যান এবং আপনার এজেন্টকে বিজ্ঞান সম্পর্কিত প্রশ্ন জিজ্ঞাসা করুন।
4. সরঞ্জাম সহ এজেন্টদের ক্ষমতায়ন
কেন এজেন্টদের সরঞ্জাম প্রয়োজন? এলএলএম শক্তিশালী, কিন্তু তাদের জ্ঞান সময়ের সাথে হিমায়িত হয় এবং তারা বাইরের বিশ্বের সাথে যোগাযোগ করতে পারে না। হাতিয়ার হল সেতু। তারা একজন এজেন্টকে রিয়েল-টাইম তথ্য অ্যাক্সেস করার অনুমতি দেয় (যেমন স্টকের দাম বা খবর), ব্যক্তিগত API জিজ্ঞাসা করতে বা জাভাতে আপনি কোড করতে পারেন এমন কোনও কাজ সম্পাদন করতে পারেন।
কোড ধাপ: একটি কাস্টম টুল তৈরি করা ( StockTicker
)
এখানে, আমরা আমাদের এজেন্টকে স্টকের দাম দেখার জন্য একটি টুল দিই। এজেন্ট যুক্তি দেয় যে যখন একজন ব্যবহারকারী একটি মূল্য জিজ্ঞাসা করে, তখন এটি আমাদের জাভা পদ্ধতিতে কল করা উচিত।
// src/main/java/com/example/agent/StockTicker.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.Annotations.Schema;
import com.google.adk.tools.FunctionTool;
import com.google.adk.web.AdkWebServer;
import java.util.Map;
public class StockTicker {
public static void main(String[] args) {
AdkWebServer.start(
LlmAgent.builder()
.name("stock_agent")
.instruction("""
You are a stock exchange ticker expert.
When asked about the stock price of a company,
use the `lookup_stock_ticker` tool to find the information.
""")
.model("gemini-2.5-flash")
.tools(FunctionTool.create(StockTicker.class, "lookupStockTicker"))
.build()
);
}
@Schema(
name = "lookup_stock_ticker",
description = "Lookup stock price for a given company or ticker"
)
public static Map<String, String> lookupStockTicker(
@Schema(name = "company_name_or_stock_ticker", description = "The company name or stock ticker")
String ticker) {
// ... (logic to return a stock price)
}
}
এজেন্টদের আরও স্মার্ট করে তুলতে এবং তাদের বিশ্বের সাথে ইন্টারঅ্যাক্ট করার ক্ষমতা দিতে (বা আপনার নিজের কোড, API, পরিষেবা ইত্যাদির সাথে) আপনি এজেন্টকে টুলস ব্যবহার করার জন্য কনফিগার করতে পারেন, এবং বিশেষ করে কাস্টম কোড টুল, tools()
পদ্ধতির মাধ্যমে, এটি একটি FunctionTool.create(...)
পাস করে।
FunctionTool
একটি ক্লাস এবং একটি পদ্ধতির নাম প্রয়োজন যা আপনার নিজস্ব স্ট্যাটিক পদ্ধতির দিকে নির্দেশ করে — এটি একটি ক্লাসের একটি উদাহরণ এবং সেই বস্তুর একটি উদাহরণ পদ্ধতির নাম পাস করাও সম্ভব।
@Schema
টীকা-এর মাধ্যমে উভয় পদ্ধতির name
এবং description
এবং এর পরামিতি উল্লেখ করা গুরুত্বপূর্ণ, কারণ এই তথ্যটি অন্তর্নিহিত LLM দ্বারা ব্যবহৃত হবে যাতে একটি প্রদত্ত পদ্ধতিকে কখন এবং কীভাবে কল করা উচিত।
সমানভাবে গুরুত্বপূর্ণ, কীভাবে এবং কখন টুলটি ব্যবহার করতে হবে সে সম্পর্কে স্পষ্ট নির্দেশাবলী দিয়ে এলএলএম-কে সাহায্য করা ভাল। মডেলটি নিজেরাই এটি বের করতে সক্ষম হতে পারে, কিন্তু আপনি যদি instruction()
পদ্ধতিতে সুস্পষ্ট ব্যাখ্যা দেন, তাহলে আপনার ফাংশনটিকে যথাযথভাবে বলা হওয়ার সম্ভাবনা বেশি থাকে।
এই পদ্ধতিতে একটি Map
ফেরত দেওয়া উচিত। সাধারণত, ধারণাটি হল একটি কী সহ একটি মানচিত্র ফেরত দেওয়া যা ফলাফলের প্রতিনিধিত্ব করে, যেমন stock_price
, এবং স্টক মূল্যের মান এর সাথে যুক্ত করা। অবশেষে, আপনি অপারেশনের সাফল্যের সংকেত দিতে একটি অতিরিক্ত সাফল্য / সত্যিকারের কী জোড়া যোগ করতে পারেন। এবং ত্রুটির ক্ষেত্রে, আপনাকে একটি কী সহ একটি মানচিত্র ফেরত দিতে হবে, উদাহরণস্বরূপ, error
, এবং সংশ্লিষ্ট মানের সাথে ত্রুটি বার্তাটি যুক্ত করুন৷ এটি এলএলএমকে বুঝতে সাহায্য করে যে কলটি সফল হয়েছে বা কোনো কারণে ব্যর্থ হয়েছে কিনা।
- সফল হলে, ফেরত দিন:
{"stock_price": 123}
- ত্রুটি হলে, ফেরত দিন:
{"error": "Impossible to retrieve stock price for XYZ"}
তারপর নিম্নলিখিত কমান্ড দিয়ে এই ক্লাস চালান:
mvn compile exec:java -Dexec.mainClass=com.example.agent.StockTicker
5. আপ-টু-ডেট তথ্যের জন্য Google অনুসন্ধানের শক্তি
জাভার জন্য ADK মুষ্টিমেয় শক্তিশালী টুলের সাথে আসে, যার মধ্যে রয়েছে GoogleSearchTool
. এই টুলের সাহায্যে, আপনার এজেন্ট তার লক্ষ্যে পৌঁছানোর জন্য প্রাসঙ্গিক তথ্য খুঁজে পেতে Google অনুসন্ধান ব্যবহার করার অনুরোধ করতে পারে।
প্রকৃতপক্ষে, একটি এলএলএম-এর জ্ঞান সময়মতো হিমায়িত হয়: এটি একটি নির্দিষ্ট তারিখ ("কাট-অফ ডেট") পর্যন্ত ডেটা সহ প্রশিক্ষণ দেওয়া হয়েছে যা তথ্য সংগ্রহ করার সময় পর্যন্ত আপ-টু-ডেট। এর মানে হল যে এলএলএমগুলি সাম্প্রতিক ঘটনাগুলি সম্পর্কে অগত্যা নাও জানতে পারে, বা তাদের জ্ঞান সীমিত এবং অগভীর হতে পারে এবং একটি সার্চ ইঞ্জিনের সাহায্য তাদের স্মৃতিকে সতেজ করতে পারে বা বিষয়টি সম্পর্কে তাদের আরও শেখাতে পারে।
আসুন এই সাধারণ সংবাদ অনুসন্ধান এজেন্টের দিকে নজর দেওয়া যাক:
// src/main/java/com/example/agent/LatestNews.java
package com.example.agent;
import java.time.LocalDate;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;
public class LatestNews {
public static void main(String[] args) {
AdkWebServer.start(LlmAgent.builder()
.name("news-search-agent")
.description("A news search agent")
.instruction("""
You are a news search agent.
Use the `google_search` tool
when asked to search for recent events and information.
Today is \
""" + LocalDate.now())
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.build());
}
}
লক্ষ্য করুন কিভাবে আমরা সার্চ টুলের একটি উদাহরণ এর সাথে পাস করেছি: tools(new GoogleSearchTool())
। This is what gives our agent the ability to get up to speed with the latest information that can be found on the web. Also, the prompt specified the date of the day, as it might help the LLM understand when questions are about past information and the lookup of more recent information is required.
Then run this class with the following command:
mvn compile exec:java -Dexec.mainClass=com.example.agent.LatestNews
Feel free to play with the prompt, to ask for different outcomes in terms of style, of conciseness, or focus, etc.
Code Step: The Search Agent as a Tool
Instead of passing the GoogleSearchTool
to an agent directly as a tool, you can create a dedicated search agent that encapsulates the search functionality and expose that agent as a tool to a higher-level agent.
This is an advanced concept that allows you to delegate complex behaviors (like searching and summarizing the results) to a specialized sub-agent. This approach is often useful for more complex workflows, as built-in tools can't be used with custom code-based tools.
// src/main/java/com/example/agent/SearchAgentAsTool.java
package com.example.agent;
import java.time.LocalDate;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.AgentTool;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;
public class SearchAgentAsTool {
public static void main(String[] args) {
// 1. Define the specialized Search Agent
LlmAgent searchAgent = LlmAgent.builder()
.name("news-search-agent-tool")
.description("Searches for recent events and provides a concise summary.")
.instruction("""
You are a concise information retrieval specialist.
Use the `google_search` tool to find information.
Always provide the answer as a short,
direct summary, without commentary.
Today is \
""" + LocalDate.now())
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool()) // This agent uses the Google Search Tool
.build();
// 2. Wrap the Search Agent as a Tool
AgentTool searchTool = AgentTool.create(searchAgent);
// 3. Define the Main Agent that uses the Search Agent Tool
AdkWebServer.start(LlmAgent.builder()
.name("main-researcher")
.description("Main agent for answering complex, up-to-date questions.")
.instruction("""
You are a sophisticated research assistant.
When the user asks a question that requires up-to-date or external information,
you MUST use the `news-search-agent-tool` to get the facts before answering.
After the tool returns the result, synthesize the final answer for the user.
""")
.model("gemini-2.5-flash")
.tools(searchTool) // This agent uses the Search Agent as a tool
.build()
);
}
}
The AgentTool.create(searchAgent)
line is the key concept here. It registers the entire searchAgent
(with its own internal logic, prompt, and tools) as a single callable tool for the mainAgent
. এটি মডুলারিটি এবং পুনরায় ব্যবহারযোগ্যতা প্রচার করে।
Run this class with the following command:
mvn compile exec:java -Dexec.mainClass=com.example.agent.SearchAgentAsTool
For mundane questions, the agent will reply from his own knowledge base, but when asked about recent events, it will delegate the search to the specialized search agent using the Google Search tool.
6. Mastering Agentic Workflows
For complex problems, a single agent is not enough. When given a goal that consists of too many sub-tasks, with a huge prompt explaining with too much detail, or with access to a huge number of functions, LLMs struggle, and their performance and accuracy degrade.
The key is to divide and conquer by orchestrating multiple specialized agents. Fortunately, ADK comes with different built-in specialized agents:
- Normal agent with
subAgent()
to delegate tasks to, -
SequentialAgent
, to do tasks in a sequence, -
ParallelAgent
, to execute agents in parallel, -
LoopAgent
, typically for going through a refinement process as many times as needed.
What are the key use cases, and the pros and cons of each workflow, please have a look at the table below. But know that the real power will actually come from the combination of several of them!
কর্মপ্রবাহ | ADK Class | কেস ব্যবহার করুন | পেশাদার | কনস |
Sub-Agents | | User-driven, flexible tasks where the next step is not always known. | High flexibility, conversational, great for user-facing bots. | Less predictable, relies on LLM reasoning for flow control. |
অনুক্রমিক | | Fixed, multi-step processes where order is critical. | Predictable, reliable, easy to debug, guarantees order. | Inflexible, can be slower if tasks could be parallelized. |
সমান্তরাল | | Gathering data from multiple sources or running independent tasks. | Highly efficient, significantly reduces latency for I/O-bound tasks. | All tasks run; no short-circuiting. Less suitable for tasks with dependencies. |
লুপ | | Iterative refinement, self-correction, or processes that repeat until a condition is met. | Powerful for complex problem-solving, enables agents to improve their own work. | Can lead to infinite loops if not designed carefully (always use maxIterations!). |
7. Agentic Workflows — Delegation with Sub-Agents
A supervisor agent can delegate particular tasks to sub-agents. For example, imagine the agent for an e-commerce website that would delegate order related questions to one agent ("what's the status of my order?") and the after sale service questions to another agent ("I don't know how to turn it on!"). This is the use case we are going to discuss.
// src/main/java/com/example/agent/SupportAgent.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.web.AdkWebServer;
public class SupportAgent {
public static void main(String[] args) {
LlmAgent topicSearchAgent = LlmAgent.builder()
.name("order-agent")
.description("Order agent")
.instruction("""
Your role is to help our customers
with all the questions they may have about their orders.
Always respond that the order has been received, prepared,
and is now out for delivery.
""")
.model("gemini-2.5-flash")
.build();
LlmAgent socialMediaAgent = LlmAgent.builder()
.name("after-sale-agent")
.description("After sale agent")
.instruction("""
You are an after sale agent,
helping customers with the product they received.
When a customer has a problem,
suggest the person to switch the product off and on again.
""")
.model("gemini-2.5-flash")
.build();
AdkWebServer.start(LlmAgent.builder()
.name("support-agent")
.description("Customer support agent")
.instruction("""
Your role is help our customers.
Call the `order-agent` for all questions related to order status.
Call the `after-sale-agent` for inquiries about the received product.
""")
.model("gemini-2.5-flash")
.subAgents(socialMediaAgent, topicSearchAgent)
.build()
);
}
}
The key line here is where the subAgents()
method is called, passing in the two sub-agents whose specific role will be handled separately by each other.
Run the example above with the following command:
mvn compile exec:java -Dexec.mainClass=com.example.agent.SupportAgent
This concept of delegating tasks to sub-agents mirrors effective human management, where a good manager (the supervisor agent) relies on specialized employees (the sub-agents) to handle specific tasks for which they have greater expertise. The supervisor doesn't need to know the minutiae of every process; instead, it intelligently routes a customer's request (like an order inquiry or a technical problem) to the most qualified 'team member,' ensuring a higher quality and more efficient response than one generalist could provide alone. Furthermore, these sub-agents can fully concentrate on their individual assignments without needing to understand the entirety of the complex overarching process.
8. Agentic Workflows — The Assembly Line
When the order of operations matters, use a SequentialAgent
. It's like an assembly line, executing sub-agents in a fixed order where each step can depend on the previous one.
Let's imagine an English poet collaborates with an English-French translator to create poems first in English and then translate them into French:
// src/main/java/com/example/agent/PoetAndTranslator.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.web.AdkWebServer;
public class PoetAndTranslator {
public static void main(String[] args) {
LlmAgent poet = LlmAgent.builder()
.name("poet-agent")
.description("Poet writing poems")
.model("gemini-2.5-flash")
.instruction("""
You are a talented poet,
who writes short and beautiful poems.
""")
.outputKey("poem")
.build();
LlmAgent translator = LlmAgent.builder()
.name("translator-agent")
.description("English to French translator")
.model("gemini-2.5-flash")
.instruction("""
As an expert English-French translator,
your role is to translate the following poem into French,
ensuring the poem still rhymes even after translation:
{poem}
""")
.outputKey("translated-poem")
.build();
AdkWebServer.start(SequentialAgent.builder()
.name("poet-and-translator")
.subAgents(poet, translator)
.build());
}
}
Run the example to get a poem in English, then translated into French, with the following command:
mvn compile exec:java -Dexec.mainClass=com.example.agent.PoetAndTranslator
This systematic decomposition of complex tasks into smaller, ordered sub-tasks ensures a more deterministic and dependable process, significantly enhancing the likelihood of a successful outcome compared to relying on a single, broadly purposed agent.
Effectively decomposing a task into a sequence of sub-tasks (when possible and when it makes sense) is crucial for achieving more deterministic and successful outcomes, as it allows for structured progression and dependency management between steps.
9. Agentic Workflows — Working in Parallel
When tasks are independent, a ParallelAgent
provides a huge efficiency boost by running them simultaneously. In the following example, we'll even be combining a SequentialAgent
with a ParallelAgent
: the parallel tasks run first, and then a final agent summarizes the outcome of the parallel tasks.
Let's build a company detective whose job will be to search for information about:
- The profile of the company (CEO, headquarters, motto, etc.)
- The latest news about the company.
- Details about the financials of the company.
// src/main/java/com/example/agent/CompanyDetective.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.ParallelAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;
public class CompanyDetective {
public static void main(String[] args) {
var companyProfiler = LlmAgent.builder()
.name("company-profiler")
.description("Provides a general overview of a company.")
.instruction("""
Your role is to provide a brief overview of the given company.
Include its mission, headquarters, and current CEO.
Use the Google Search Tool to find this information.
""")
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.outputKey("profile")
.build();
var newsFinder = LlmAgent.builder()
.name("news-finder")
.description("Finds the latest news about a company.")
.instruction("""
Your role is to find the top 3-4 recent news headlines for the given company.
Use the Google Search Tool.
Present the results as a simple bulleted list.
""")
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.outputKey("news")
.build();
var financialAnalyst = LlmAgent.builder()
.name("financial-analyst")
.description("Analyzes the financial performance of a company.")
.instruction("""
Your role is to provide a snapshot of the given company's recent financial performance.
Focus on stock trends or recent earnings reports.
Use the Google Search Tool.
""")
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.outputKey("financials")
.build();
var marketResearcher = ParallelAgent.builder()
.name("market-researcher")
.description("Performs comprehensive market research on a company.")
.subAgents(
companyProfiler,
newsFinder,
financialAnalyst
)
.build();
var reportCompiler = LlmAgent.builder()
.name("report-compiler")
.description("Compiles a final market research report.")
.instruction("""
Your role is to synthesize the provided information into a coherent market research report.
Combine the company profile, latest news, and financial analysis into a single, well-formatted report.
## Company Profile
{profile}
## Latest News
{news}
## Financial Snapshot
{financials}
""")
.model("gemini-2.5-flash")
.build();
AdkWebServer.start(SequentialAgent.builder()
.name("company-detective")
.description("Collects various information about a company.")
.subAgents(
marketResearcher,
reportCompiler
).build());
}
}
As usual, you can run the agent with the following command:
mvn compile exec:java -Dexec.mainClass=com.example.agent.CompanyDetective
This agent demonstrates a powerful combination of workflows, with both parallel and sequential agents put to good use, in an efficient way thanks to parallelization of information research and synthesis.
10. Agentic Workflows — Iterative Refinement
For tasks requiring a "generate → review → refine" cycle, use a LoopAgent
. It automates iterative improvement until a goal is met. Similarly to the SequentialAgent
, the LoopAgent
will call sub-agent serially, but it will loop back at the beginning. It is the LLM used internally by the agent that will decide whether or not to request the call to a special tool, the exit_loop
built-in tool, to stop the execution of the loop.
The code refiner example below, using a LoopAgent
, automates code refinement: generate, review, correct. This mimics human development. A code generator first generates the requested code, saves it in the agent state under the generated_code
key. A code reviewer then reviews the generated code, and either provides feedback (under the feedback
key), or calls an exit loop tool to end the iteration early.
Let's have a look at the code:
// src/main/java/com/example/agent/CodeRefiner.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.LoopAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.tools.ExitLoopTool;
import com.google.adk.web.AdkWebServer;
public class CodeRefiner {
public static void main(String[] args) {
var codeGenerator = LlmAgent.builder()
.name("code-generator")
.description("Writes and refines code based on a request and feedback.")
.instruction("""
Your role is to write a Python function based on the user's request.
In the first turn, write the initial version of the code.
In subsequent turns, you will receive feedback on your code.
Your task is to refine the code based on this feedback.
Previous feedback (if any):
{feedback?}
""")
.model("gemini-2.5-flash")
.outputKey("generated_code")
.build();
var codeReviewer = LlmAgent.builder()
.name("code-reviewer")
.description("Reviews code and decides if it's complete or needs more work.")
.instruction("""
Your role is to act as a senior code reviewer.
Analyze the provided Python code for correctness, style, and potential bugs.
Code to review:
{generated_code}
If the code is perfect and meets the user's request,
you MUST call the `exit_loop` tool.
Otherwise, provide constructive feedback for the `code-generator to improve the code.
""")
.model("gemini-2.5-flash")
.outputKey("feedback")
.tools(ExitLoopTool.INSTANCE)
.build();
var codeRefinerLoop = LoopAgent.builder()
.name("code-refiner-loop")
.description("Iteratively generates and reviews code until it is correct.")
.subAgents(
codeGenerator,
codeReviewer
)
.maxIterations(3) // Safety net to prevent infinite loops
.build();
var finalPresenter = LlmAgent.builder()
.name("final-presenter")
.description("Presents the final, accepted code to the user.")
.instruction("""
The code has been successfully generated and reviewed.
Present the final version of the code to the user in a clear format.
Final Code:
{generated_code}
""")
.model("gemini-2.5-flash")
.build();
AdkWebServer.start(SequentialAgent.builder()
.name("code-refiner-assistant")
.description("Manages the full code generation and refinement process.")
.subAgents(
codeRefinerLoop,
finalPresenter)
.build());
}
}
Run this agent with the following command:
mvn compile exec:java -Dexec.mainClass=com.example.agent.CodeRefiner
Feedback/refine loops, implemented using the LoopAgent
, are indispensable for solving problems that require iterative improvement and self-correction, closely mimicking human cognitive processes. This design pattern is particularly useful for tasks where the initial output is rarely perfect, such as code generation, creative writing, design iteration, or complex data analysis. By cycling the output through a specialized reviewer agent that provides structured feedback, the generating agent can continuously refine its work until a predefined completion criterion is met, leading to demonstrably higher quality and more reliable final results than a single-pass approach.
11. Congratulations!
You've successfully built and explored a variety of AI agents, from simple conversationalists to complex, multi-agent systems. You've learned the core concepts of the ADK for Java: defining agents with instructions, empowering them with tools, and orchestrating them into powerful workflows.
এরপর কি?
- Explore the official ADK for Java GitHub repository .
- Learn more about the framework in its documentation .
- Read about the various agentic workflows in this blog series and about the various tools available.
- Dive deeper into the other built-in tools and advanced callbacks.
- Handle context, state, and artifacts, for richer and multimodal interactions.
- Implement and apply plugins that plug into the lifecycle of your agents.
- Try building your own agent that solves a real-world problem!
1. Welcome, AI agent developers!
In this codelab, you'll learn how to build AI agents in Java , using the Agents Development Kit (ADK) for Java . We'll move beyond simple Large Language Model (LLM) API calls to create autonomous AI agents that can reason, plan, use tools, and work together to solve complex problems.
You will start by redeeming the Google Cloud credits, setting up your Google Cloud environment, then building your first simple agent, and progressively adding more advanced capabilities like custom tools, web search, and multi-agent orchestration.
আপনি কি শিখবেন
- How to create a basic, persona-driven AI agent.
- How to empower agents with custom and built-in tools (like Google Search).
- How to add your own tools implemented in Java.
- How to orchestrate multiple agents into powerful sequential, parallel, and looping workflows.
আপনি কি প্রয়োজন হবে
- A web browser that we'll use in Incognito mode.
- A personal Gmail account.
- A new Google Cloud project associated with your personal Gmail account.
- A billing account created with the redeemed Google Cloud credits.
- The git command-line tool to check out the source code.
- Java 17+ and Apache Maven.
- A text editor or IDE, such as IntelliJ IDEA or VS Code.
It's possible to use the built-in VS Code editor in Cloud Shell, in the Google Cloud console.
2. Setup: Your Environment
Claiming Google Cloud credits for the workshop
For an instructor-led workshop, you will have received a link to the website where you can claim Google cloud credits to use for the workshop.
- Use a personal Google account : It is important to use a personal Google account (like a gmail.com address) as corporate or school email addresses will not work .
- Use Google Chrome in incognito mode : This is recommended to create a clean session and prevent conflicts with other Google accounts.
- Use the special event link : A special link for the event, which looks something like https://trygcp.dev/event/xxx followed by an event code (here "xxx" in this example), should be used.
- Accept the terms of service : After signing in, you will be presented with the Google Cloud Platform terms of service, which you need to accept to continue.
- Create a new project : A new empty project must be created from the Google Cloud Console .
- Link a billing account : Link the newly created project to a billing account.
- Confirm the credit : The following video shows how to confirm that the credit is applied to the project by checking the "credits" section in the billing page.
Feel free to check out this video which explains how to redeem and apply the credits.
Create and Configure Your API Key
To authenticate your ADK AI agents with the Gemini API for this codelab, you'll use an API key associated with your Google Cloud project.
- Generate an API Key:
- Go to Google AI Studio and click on the "Get API key" link at the bottom of the left side panel.
- Select Projects and then click the Import projects button.
- Search for and select the Google Cloud project you want to import, then select the Import button.
- Once the project is imported, go to the API Keys page from the Dashboard menu, and create an API key in the project you just imported.
- Make note of the API key .
- Set the Environment Variable: Your agent needs to access this key. The standard way is by setting an environment variable named
GOOGLE_API_KEY
.
- macOS / Linux: Open your terminal and run the following command, replacing
"your-api-key"
with the key you just copied. To make this permanent, add this line to your shell's startup file (eg,~/.bash_profile
,~/.zshrc
).
export GOOGLE_API_KEY="your-api-key"
- Windows (Command Prompt): Open a new command prompt and run:
setx GOOGLE_API_KEY "your-api-key"
- You will need to restart your command prompt for this change to take effect.
- Windows (PowerShell): Open a PowerShell terminal and run:
$env:GOOGLE_API_KEY="your-api-key"
- To make this change permanent in PowerShell, you'll need to add it to your profile script.
3. Getting Started: Your First Agent
The best way to start a new project is by using the ADK for Java GitHub template . It provides the project structure and all the necessary dependencies.
If you have a Github account, you can do the following: Use this template
> Create a new repository
, then checkout the code locally with the git clone
command.
Here is a screenshot showing the top-right menu for using the template.
The other approach is to simply clone that repository directly, with:
git clone https://github.com/glaforge/adk-java-maven-template.git
Then cd
into adk-java-maven-template
.
To check that you are ready to get started with coding your first AI agent in Java, ensure you can compile the code in this project with:
mvn compile
Code Step: A Friendly Science Teacher Agent
The fundamental building block in ADK is the LlmAgent
class. Think of it as an AI with a specific personality and goal, powered by a Large Language Model. We'll later add more capabilities via tools, and make it more powerful by collaborating hand-in-hand with other similar agents.
Let's create a new Java class, in the com.example.agent
package, and call it ScienceTeacher
.
This is the "Hello, World!" of agent creation. We're defining a simple agent with the persona of a science teacher.
// src/main/java/com/example/agent/ScienceTeacher.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.web.AdkWebServer;
public class ScienceTeacher {
public static void main(String[] args) {
AdkWebServer.start(
LlmAgent.builder()
.name("science-teacher")
.description("A friendly science teacher")
.instruction("""
You are a science teacher for teenagers.
You explain science concepts in a simple, concise and direct way.
""")
.model("gemini-2.5-flash")
.build()
);
}
}
The AI agent is configured via the LlmAgent.builder()
method. The name()
, description()
, and model()
parameters are mandatory, and to give a specific personality and proper behavior to your agent, you should always give detailed guidance via the instruction()
method.
Here we chose to use the Gemini 2.5 Flash model, but feel free to try Gemini 2.5 Pro as well, for more complicated tasks.
This agent is wrapped within the AdkWebServer.start()
method. This is the so-called ADK Dev UI chat interface. It allows you to converse with the agent via a typical chat interface. Furthermore, it's of great help if you want to understand what's going on under the hood, like all the events that are flowing through the system, the requests and responses sent to the LLM.
To compile and run this agent locally, run the following command:
mvn compile exec:java -Dexec.mainClass=com.example.agent.ScienceTeacher
Then head over to your browser at http://localhost:8080 . You should see the UI as shown in the screenshot below. Go ahead and ask science related questions to your agent.
4. Empowering Agents with Tools
Why do agents need tools? LLMs are powerful, but their knowledge is frozen in time and they can't interact with the outside world. Tools are the bridge. They allow an agent to access real-time information (like stock prices or news), query private APIs, or perform any action you can code in Java.
Code Step: Creating a Custom Tool ( StockTicker
)
Here, we give our agent a tool to look up stock prices. The agent reasons that when a user asks for a price, it should call our Java method.
// src/main/java/com/example/agent/StockTicker.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.Annotations.Schema;
import com.google.adk.tools.FunctionTool;
import com.google.adk.web.AdkWebServer;
import java.util.Map;
public class StockTicker {
public static void main(String[] args) {
AdkWebServer.start(
LlmAgent.builder()
.name("stock_agent")
.instruction("""
You are a stock exchange ticker expert.
When asked about the stock price of a company,
use the `lookup_stock_ticker` tool to find the information.
""")
.model("gemini-2.5-flash")
.tools(FunctionTool.create(StockTicker.class, "lookupStockTicker"))
.build()
);
}
@Schema(
name = "lookup_stock_ticker",
description = "Lookup stock price for a given company or ticker"
)
public static Map<String, String> lookupStockTicker(
@Schema(name = "company_name_or_stock_ticker", description = "The company name or stock ticker")
String ticker) {
// ... (logic to return a stock price)
}
}
To make agents smarter and give them the ability to interact with the world (or with your own code, APIs, services, etc.) you can configure the agent to use tools, and in particular custom code tools, via the tools()
method, passing it a FunctionTool.create(...)
.
The FunctionTool
needs a class and a method name pointing at your own static method — it's also possible to pass an instance of a class and the name of an instance method of that object.
It is important to specify the name
and description
of both the method, and its parameters, via the @Schema
annotation, as this information will be used by the underlying LLM to figure out when and how it should call a given method.
Equally important, it's better to help the LLM with clear instructions about how and when to use the tool. The model may be able to figure it out on its own, but if you give explicit explanations in the instruction()
method, your function has higher chances to be called appropriately.
This method should return a Map
. Usually, the idea is to return a map with a key representing the result, like stock_price
, and associate the value of the stock price to it. Eventually, you can add an extra success / true key pair to signal the success of the operation. And in case of error, you should return a map with a key called, for example, error
, and associate the error message in the associated value. This helps the LLM understand if the call succeeded or failed for some reason.
- On success, return:
{"stock_price": 123}
- On error, return:
{"error": "Impossible to retrieve stock price for XYZ"}
Then run this class with the following command:
mvn compile exec:java -Dexec.mainClass=com.example.agent.StockTicker
5. The power of Google Search for up-to-date information
ADK for Java comes with a handful of powerful tools, among which is the GoogleSearchTool
. With this tool, your agent can request the use of Google Search to find relevant information to reach its goal.
Indeed, the knowledge of an LLM is frozen in time: it has been trained until a certain date (the "cut-off date") with data that is also as up-to-date as when the information was collected. This means that LLMs may not necessarily know about recent events, or their knowledge may be limited and shallow, and the help of a search engine might refresh their memory or teach them more about the topic.
Let's have a look at this simple news search agent:
// src/main/java/com/example/agent/LatestNews.java
package com.example.agent;
import java.time.LocalDate;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;
public class LatestNews {
public static void main(String[] args) {
AdkWebServer.start(LlmAgent.builder()
.name("news-search-agent")
.description("A news search agent")
.instruction("""
You are a news search agent.
Use the `google_search` tool
when asked to search for recent events and information.
Today is \
""" + LocalDate.now())
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.build());
}
}
Notice how we passed an instance of the search tool with: tools(new GoogleSearchTool())
. This is what gives our agent the ability to get up to speed with the latest information that can be found on the web. Also, the prompt specified the date of the day, as it might help the LLM understand when questions are about past information and the lookup of more recent information is required.
Then run this class with the following command:
mvn compile exec:java -Dexec.mainClass=com.example.agent.LatestNews
Feel free to play with the prompt, to ask for different outcomes in terms of style, of conciseness, or focus, etc.
Code Step: The Search Agent as a Tool
Instead of passing the GoogleSearchTool
to an agent directly as a tool, you can create a dedicated search agent that encapsulates the search functionality and expose that agent as a tool to a higher-level agent.
This is an advanced concept that allows you to delegate complex behaviors (like searching and summarizing the results) to a specialized sub-agent. This approach is often useful for more complex workflows, as built-in tools can't be used with custom code-based tools.
// src/main/java/com/example/agent/SearchAgentAsTool.java
package com.example.agent;
import java.time.LocalDate;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.AgentTool;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;
public class SearchAgentAsTool {
public static void main(String[] args) {
// 1. Define the specialized Search Agent
LlmAgent searchAgent = LlmAgent.builder()
.name("news-search-agent-tool")
.description("Searches for recent events and provides a concise summary.")
.instruction("""
You are a concise information retrieval specialist.
Use the `google_search` tool to find information.
Always provide the answer as a short,
direct summary, without commentary.
Today is \
""" + LocalDate.now())
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool()) // This agent uses the Google Search Tool
.build();
// 2. Wrap the Search Agent as a Tool
AgentTool searchTool = AgentTool.create(searchAgent);
// 3. Define the Main Agent that uses the Search Agent Tool
AdkWebServer.start(LlmAgent.builder()
.name("main-researcher")
.description("Main agent for answering complex, up-to-date questions.")
.instruction("""
You are a sophisticated research assistant.
When the user asks a question that requires up-to-date or external information,
you MUST use the `news-search-agent-tool` to get the facts before answering.
After the tool returns the result, synthesize the final answer for the user.
""")
.model("gemini-2.5-flash")
.tools(searchTool) // This agent uses the Search Agent as a tool
.build()
);
}
}
The AgentTool.create(searchAgent)
line is the key concept here. It registers the entire searchAgent
(with its own internal logic, prompt, and tools) as a single callable tool for the mainAgent
. এটি মডুলারিটি এবং পুনরায় ব্যবহারযোগ্যতা প্রচার করে।
Run this class with the following command:
mvn compile exec:java -Dexec.mainClass=com.example.agent.SearchAgentAsTool
For mundane questions, the agent will reply from his own knowledge base, but when asked about recent events, it will delegate the search to the specialized search agent using the Google Search tool.
6. Mastering Agentic Workflows
For complex problems, a single agent is not enough. When given a goal that consists of too many sub-tasks, with a huge prompt explaining with too much detail, or with access to a huge number of functions, LLMs struggle, and their performance and accuracy degrade.
The key is to divide and conquer by orchestrating multiple specialized agents. Fortunately, ADK comes with different built-in specialized agents:
- Normal agent with
subAgent()
to delegate tasks to, -
SequentialAgent
, to do tasks in a sequence, -
ParallelAgent
, to execute agents in parallel, -
LoopAgent
, typically for going through a refinement process as many times as needed.
What are the key use cases, and the pros and cons of each workflow, please have a look at the table below. But know that the real power will actually come from the combination of several of them!
কর্মপ্রবাহ | ADK Class | কেস ব্যবহার করুন | পেশাদার | কনস |
Sub-Agents | | User-driven, flexible tasks where the next step is not always known. | High flexibility, conversational, great for user-facing bots. | Less predictable, relies on LLM reasoning for flow control. |
অনুক্রমিক | | Fixed, multi-step processes where order is critical. | Predictable, reliable, easy to debug, guarantees order. | Inflexible, can be slower if tasks could be parallelized. |
সমান্তরাল | | Gathering data from multiple sources or running independent tasks. | Highly efficient, significantly reduces latency for I/O-bound tasks. | All tasks run; no short-circuiting. Less suitable for tasks with dependencies. |
লুপ | | Iterative refinement, self-correction, or processes that repeat until a condition is met. | Powerful for complex problem-solving, enables agents to improve their own work. | Can lead to infinite loops if not designed carefully (always use maxIterations!). |
7. Agentic Workflows — Delegation with Sub-Agents
A supervisor agent can delegate particular tasks to sub-agents. For example, imagine the agent for an e-commerce website that would delegate order related questions to one agent ("what's the status of my order?") and the after sale service questions to another agent ("I don't know how to turn it on!"). This is the use case we are going to discuss.
// src/main/java/com/example/agent/SupportAgent.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.web.AdkWebServer;
public class SupportAgent {
public static void main(String[] args) {
LlmAgent topicSearchAgent = LlmAgent.builder()
.name("order-agent")
.description("Order agent")
.instruction("""
Your role is to help our customers
with all the questions they may have about their orders.
Always respond that the order has been received, prepared,
and is now out for delivery.
""")
.model("gemini-2.5-flash")
.build();
LlmAgent socialMediaAgent = LlmAgent.builder()
.name("after-sale-agent")
.description("After sale agent")
.instruction("""
You are an after sale agent,
helping customers with the product they received.
When a customer has a problem,
suggest the person to switch the product off and on again.
""")
.model("gemini-2.5-flash")
.build();
AdkWebServer.start(LlmAgent.builder()
.name("support-agent")
.description("Customer support agent")
.instruction("""
Your role is help our customers.
Call the `order-agent` for all questions related to order status.
Call the `after-sale-agent` for inquiries about the received product.
""")
.model("gemini-2.5-flash")
.subAgents(socialMediaAgent, topicSearchAgent)
.build()
);
}
}
The key line here is where the subAgents()
method is called, passing in the two sub-agents whose specific role will be handled separately by each other.
Run the example above with the following command:
mvn compile exec:java -Dexec.mainClass=com.example.agent.SupportAgent
This concept of delegating tasks to sub-agents mirrors effective human management, where a good manager (the supervisor agent) relies on specialized employees (the sub-agents) to handle specific tasks for which they have greater expertise. The supervisor doesn't need to know the minutiae of every process; instead, it intelligently routes a customer's request (like an order inquiry or a technical problem) to the most qualified 'team member,' ensuring a higher quality and more efficient response than one generalist could provide alone. Furthermore, these sub-agents can fully concentrate on their individual assignments without needing to understand the entirety of the complex overarching process.
8. Agentic Workflows — The Assembly Line
When the order of operations matters, use a SequentialAgent
. It's like an assembly line, executing sub-agents in a fixed order where each step can depend on the previous one.
Let's imagine an English poet collaborates with an English-French translator to create poems first in English and then translate them into French:
// src/main/java/com/example/agent/PoetAndTranslator.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.web.AdkWebServer;
public class PoetAndTranslator {
public static void main(String[] args) {
LlmAgent poet = LlmAgent.builder()
.name("poet-agent")
.description("Poet writing poems")
.model("gemini-2.5-flash")
.instruction("""
You are a talented poet,
who writes short and beautiful poems.
""")
.outputKey("poem")
.build();
LlmAgent translator = LlmAgent.builder()
.name("translator-agent")
.description("English to French translator")
.model("gemini-2.5-flash")
.instruction("""
As an expert English-French translator,
your role is to translate the following poem into French,
ensuring the poem still rhymes even after translation:
{poem}
""")
.outputKey("translated-poem")
.build();
AdkWebServer.start(SequentialAgent.builder()
.name("poet-and-translator")
.subAgents(poet, translator)
.build());
}
}
Run the example to get a poem in English, then translated into French, with the following command:
mvn compile exec:java -Dexec.mainClass=com.example.agent.PoetAndTranslator
This systematic decomposition of complex tasks into smaller, ordered sub-tasks ensures a more deterministic and dependable process, significantly enhancing the likelihood of a successful outcome compared to relying on a single, broadly purposed agent.
Effectively decomposing a task into a sequence of sub-tasks (when possible and when it makes sense) is crucial for achieving more deterministic and successful outcomes, as it allows for structured progression and dependency management between steps.
9. Agentic Workflows — Working in Parallel
When tasks are independent, a ParallelAgent
provides a huge efficiency boost by running them simultaneously. In the following example, we'll even be combining a SequentialAgent
with a ParallelAgent
: the parallel tasks run first, and then a final agent summarizes the outcome of the parallel tasks.
Let's build a company detective whose job will be to search for information about:
- The profile of the company (CEO, headquarters, motto, etc.)
- The latest news about the company.
- Details about the financials of the company.
// src/main/java/com/example/agent/CompanyDetective.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.ParallelAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;
public class CompanyDetective {
public static void main(String[] args) {
var companyProfiler = LlmAgent.builder()
.name("company-profiler")
.description("Provides a general overview of a company.")
.instruction("""
Your role is to provide a brief overview of the given company.
Include its mission, headquarters, and current CEO.
Use the Google Search Tool to find this information.
""")
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.outputKey("profile")
.build();
var newsFinder = LlmAgent.builder()
.name("news-finder")
.description("Finds the latest news about a company.")
.instruction("""
Your role is to find the top 3-4 recent news headlines for the given company.
Use the Google Search Tool.
Present the results as a simple bulleted list.
""")
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.outputKey("news")
.build();
var financialAnalyst = LlmAgent.builder()
.name("financial-analyst")
.description("Analyzes the financial performance of a company.")
.instruction("""
Your role is to provide a snapshot of the given company's recent financial performance.
Focus on stock trends or recent earnings reports.
Use the Google Search Tool.
""")
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.outputKey("financials")
.build();
var marketResearcher = ParallelAgent.builder()
.name("market-researcher")
.description("Performs comprehensive market research on a company.")
.subAgents(
companyProfiler,
newsFinder,
financialAnalyst
)
.build();
var reportCompiler = LlmAgent.builder()
.name("report-compiler")
.description("Compiles a final market research report.")
.instruction("""
Your role is to synthesize the provided information into a coherent market research report.
Combine the company profile, latest news, and financial analysis into a single, well-formatted report.
## Company Profile
{profile}
## Latest News
{news}
## Financial Snapshot
{financials}
""")
.model("gemini-2.5-flash")
.build();
AdkWebServer.start(SequentialAgent.builder()
.name("company-detective")
.description("Collects various information about a company.")
.subAgents(
marketResearcher,
reportCompiler
).build());
}
}
As usual, you can run the agent with the following command:
mvn compile exec:java -Dexec.mainClass=com.example.agent.CompanyDetective
This agent demonstrates a powerful combination of workflows, with both parallel and sequential agents put to good use, in an efficient way thanks to parallelization of information research and synthesis.
10. Agentic Workflows — Iterative Refinement
For tasks requiring a "generate → review → refine" cycle, use a LoopAgent
. It automates iterative improvement until a goal is met. Similarly to the SequentialAgent
, the LoopAgent
will call sub-agent serially, but it will loop back at the beginning. It is the LLM used internally by the agent that will decide whether or not to request the call to a special tool, the exit_loop
built-in tool, to stop the execution of the loop.
The code refiner example below, using a LoopAgent
, automates code refinement: generate, review, correct. This mimics human development. A code generator first generates the requested code, saves it in the agent state under the generated_code
key. A code reviewer then reviews the generated code, and either provides feedback (under the feedback
key), or calls an exit loop tool to end the iteration early.
Let's have a look at the code:
// src/main/java/com/example/agent/CodeRefiner.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.LoopAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.tools.ExitLoopTool;
import com.google.adk.web.AdkWebServer;
public class CodeRefiner {
public static void main(String[] args) {
var codeGenerator = LlmAgent.builder()
.name("code-generator")
.description("Writes and refines code based on a request and feedback.")
.instruction("""
Your role is to write a Python function based on the user's request.
In the first turn, write the initial version of the code.
In subsequent turns, you will receive feedback on your code.
Your task is to refine the code based on this feedback.
Previous feedback (if any):
{feedback?}
""")
.model("gemini-2.5-flash")
.outputKey("generated_code")
.build();
var codeReviewer = LlmAgent.builder()
.name("code-reviewer")
.description("Reviews code and decides if it's complete or needs more work.")
.instruction("""
Your role is to act as a senior code reviewer.
Analyze the provided Python code for correctness, style, and potential bugs.
Code to review:
{generated_code}
If the code is perfect and meets the user's request,
you MUST call the `exit_loop` tool.
Otherwise, provide constructive feedback for the `code-generator to improve the code.
""")
.model("gemini-2.5-flash")
.outputKey("feedback")
.tools(ExitLoopTool.INSTANCE)
.build();
var codeRefinerLoop = LoopAgent.builder()
.name("code-refiner-loop")
.description("Iteratively generates and reviews code until it is correct.")
.subAgents(
codeGenerator,
codeReviewer
)
.maxIterations(3) // Safety net to prevent infinite loops
.build();
var finalPresenter = LlmAgent.builder()
.name("final-presenter")
.description("Presents the final, accepted code to the user.")
.instruction("""
The code has been successfully generated and reviewed.
Present the final version of the code to the user in a clear format.
Final Code:
{generated_code}
""")
.model("gemini-2.5-flash")
.build();
AdkWebServer.start(SequentialAgent.builder()
.name("code-refiner-assistant")
.description("Manages the full code generation and refinement process.")
.subAgents(
codeRefinerLoop,
finalPresenter)
.build());
}
}
Run this agent with the following command:
mvn compile exec:java -Dexec.mainClass=com.example.agent.CodeRefiner
Feedback/refine loops, implemented using the LoopAgent
, are indispensable for solving problems that require iterative improvement and self-correction, closely mimicking human cognitive processes. This design pattern is particularly useful for tasks where the initial output is rarely perfect, such as code generation, creative writing, design iteration, or complex data analysis. By cycling the output through a specialized reviewer agent that provides structured feedback, the generating agent can continuously refine its work until a predefined completion criterion is met, leading to demonstrably higher quality and more reliable final results than a single-pass approach.
11. Congratulations!
You've successfully built and explored a variety of AI agents, from simple conversationalists to complex, multi-agent systems. You've learned the core concepts of the ADK for Java: defining agents with instructions, empowering them with tools, and orchestrating them into powerful workflows.
এরপর কি?
- Explore the official ADK for Java GitHub repository .
- Learn more about the framework in its documentation .
- Read about the various agentic workflows in this blog series and about the various tools available.
- Dive deeper into the other built-in tools and advanced callbacks.
- Handle context, state, and artifacts, for richer and multimodal interactions.
- Implement and apply plugins that plug into the lifecycle of your agents.
- Try building your own agent that solves a real-world problem!