Setelah sebuah sesi ada, gunakan operasi-operasi ini untuk membaca, memperbarui, mengarsipkan, atau menghapusnya. Lihat Memulai sesi untuk membuat sesi dan mengirimkan pekerjaan kepadanya.
Status sesi
Sesi berkembang melalui status-status berikut. Lihat Memulai sesi untuk siklus hidup sesi.
| Status | Deskripsi |
|---|---|
idle | Agen sedang menunggu input, termasuk pesan pengguna atau konfirmasi alat. Sesi yang dibuat tanpa initial_events dimulai dalam status idle. |
running | Agen sedang aktif mengeksekusi. |
rescheduling | Terjadi kesalahan sementara, mencoba ulang secara otomatis. |
terminated | Sesi telah berakhir, baik karena kesalahan yang tidak dapat dipulihkan maupun karena telah diarsipkan. Sesi yang menyelesaikan pekerjaannya menjadi idle, bukan terminated. |
Memperbarui konfigurasi agen
Anda dapat memperbarui agent.tools dan agent.mcp_servers milik sebuah sesi, termasuk kebijakan izin dan pengaturan web per alat seperti filter domain, di tengah sesi tanpa membuat versi agen baru. Pembaruan bersifat lokal pada sesi dan tidak disebarkan kembali ke agen yang mendasarinya. allowed_domains dan blocked_domains yang diperbarui berlaku untuk sisa sesi.
Hanya tools dan mcp_servers milik agen yang dapat berubah setelah sesi dibuat. Untuk menjalankan sesi dengan nilai model, system, atau tracks yang berbeda dari milik agen, gunakan override konfigurasi agen saat Anda membuat sesi. Konfigurasi model agen, termasuk pin inference_geo-nya, juga tidak dapat berubah di tengah sesi: tetapkan pin saat Anda menyimpan agen, atau tetapkan atau hapus pin tersebut untuk satu sesi dengan override model saat Anda membuatnya. Field system yang dikonfigurasi pada agen bersifat tetap selama masa hidup sesi. Pada model yang mendukungnya, Anda masih dapat menambahkan panduan tingkat sistem di tengah sesi dengan mengirimkan event system.message.
Semantik pembaruan tools atau mcp_servers adalah penggantian penuh: array yang diberikan menjadi nilai baru. Untuk mempertahankan entri yang sudah ada, lakukan GET pada sesi, ubah array-nya, lalu POST kembali.
Sesi harus berstatus idle untuk memperbarui agen. Untuk memperbarui agen saat sesi sedang berjalan, kirimkan event user.interrupt secara tersendiri dan tunggu hingga sesi menjadi idle.
curl -sS --fail-with-body "https://haijun.my.id/v1/sessions/$SESSION_ID" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "juglow-beta: managed-agents-2026-04-01" \
-H "content-type: application/json" \
-d @- <<EOF
{
"agent": {
"tools": [
{"type": "agent_toolset_20260401"},
{"type": "mcp_toolset", "mcp_server_name": "linear"}
],
"mcp_servers": [
{"type": "url", "name": "linear", "url": "https://mcp.linear.app/sse"}
]
}
}
EOF ant beta:sessions update --session-id "$SESSION_ID" <<'YAML'
agent:
tools:
- type: agent_toolset_20260401
- type: mcp_toolset
mcp_server_name: linear
mcp_servers:
- type: url
name: linear
url: https://mcp.linear.app/sse
YAML client.beta.sessions.update(
session.id,
agent={
"tools": [
{"type": "agent_toolset_20260401"},
{"type": "mcp_toolset", "mcp_server_name": "linear"},
],
"mcp_servers": [
{"type": "url", "name": "linear", "url": "https://mcp.linear.app/sse"}
],
},
) await client.beta.sessions.update(session.id, {
agent: {
tools: [
{ type: "agent_toolset_20260401" },
{ type: "mcp_toolset", mcp_server_name: "linear" }
],
mcp_servers: [{ type: "url", name: "linear", url: "https://mcp.linear.app/sse" }]
}
}); await client.Beta.Sessions.Update(session.ID, new()
{
Agent = new()
{
Tools =
[
new BetaManagedAgentsAgentToolset20260401Params
{
Type = BetaManagedAgentsAgentToolset20260401ParamsType.AgentToolset20260401,
},
new BetaManagedAgentsMcpToolsetParams
{
Type = BetaManagedAgentsMcpToolsetParamsType.McpToolset,
McpServerName = "linear",
},
],
McpServers =
[
new()
{
Type = BetaManagedAgentsUrlMcpServerParamsType.Url,
Name = "linear",
Url = "https://mcp.linear.app/sse",
},
],
},
}); _, err = client.Beta.Sessions.Update(ctx, session.ID, juglow.BetaSessionUpdateParams{
Agent: juglow.BetaManagedAgentsSessionAgentUpdateParam{
Tools: []juglow.BetaManagedAgentsSessionAgentUpdateToolUnionParam{
{
OfAgentToolset20260401: &juglow.BetaManagedAgentsAgentToolset20260401Params{
Type: juglow.BetaManagedAgentsAgentToolset20260401ParamsTypeAgentToolset20260401,
},
},
{
OfMCPToolset: &juglow.BetaManagedAgentsMCPToolsetParams{
Type: juglow.BetaManagedAgentsMCPToolsetParamsTypeMCPToolset,
MCPServerName: "linear",
},
},
},
MCPServers: []juglow.BetaManagedAgentsURLMCPServerParams{
{
Type: juglow.BetaManagedAgentsURLMCPServerParamsTypeURL,
Name: "linear",
URL: "https://mcp.linear.app/sse",
},
},
},
})
if err != nil {
panic(err)
} client.beta().sessions().update(
session.id(),
SessionUpdateParams.builder()
.agent(BetaManagedAgentsSessionAgentUpdate.builder()
.addTool(BetaManagedAgentsAgentToolset20260401Params.builder()
.type(BetaManagedAgentsAgentToolset20260401Params.Type.AGENT_TOOLSET_20260401)
.build())
.addTool(BetaManagedAgentsMcpToolsetParams.builder()
.type(BetaManagedAgentsMcpToolsetParams.Type.MCP_TOOLSET)
.mcpServerName("linear")
.build())
.addMcpServer(BetaManagedAgentsUrlMcpServerParams.builder()
.type(BetaManagedAgentsUrlMcpServerParams.Type.URL)
.name("linear")
.url("https://mcp.linear.app/sse")
.build())
.build())
.build()
); $client->beta->sessions->update(
$session->id,
agent: BetaManagedAgentsSessionAgentUpdate::with(
tools: [
BetaManagedAgentsAgentToolset20260401Params::with(type: 'agent_toolset_20260401'),
BetaManagedAgentsMCPToolsetParams::with(mcpServerName: 'linear', type: 'mcp_toolset'),
],
mcpServers: [
BetaManagedAgentsURLMCPServerParams::with(
name: 'linear',
type: 'url',
url: 'https://mcp.linear.app/sse',
),
],
),
); client.beta.sessions.update(
session.id,
agent: {
tools: [
{type: :agent_toolset_20260401},
{type: :mcp_toolset, mcp_server_name: "linear"}
],
mcp_servers: [
{type: :url, name: "linear", url: "https://mcp.linear.app/sse"}
]
}
)Memperbarui anggaran sesi
Sesi yang dibuat dengan anggaran menerima dua jenis pembaruan anggaran: mengganti batas dengan max_list_cost baru, dan menghapusnya dengan menetapkan budget ke null. Keduanya secara otomatis melanjutkan pekerjaan yang terjeda ketika sesi mencapai batasnya. Batas pengganti dapat lebih tinggi atau lebih rendah dari batas saat ini, tetapi harus benar-benar lebih besar dari biaya daftar (list cost) yang telah dikonsumsi sesi, dan penghapusan bersifat satu arah: budget yang bukan null hanya diterima pada sesi yang saat ini memilikinya, sehingga Anda tidak dapat menambahkan kembali anggaran yang telah dihapus atau menambahkannya ke sesi yang dibuat tanpa anggaran. Lihat Anggaran sesi untuk contoh permintaan, perilaku kesalahan, dan apa saja yang dihitung ke dalam biaya daftar.
Mengambil sesi
curl -fsSL "https://haijun.my.id/v1/sessions/$SESSION_ID" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "juglow-beta: managed-agents-2026-04-01" ant beta:sessions retrieve --session-id "$SESSION_ID" retrieved = client.beta.sessions.retrieve(session.id)
print(f"Status: {retrieved.status}") const retrieved = await client.beta.sessions.retrieve(session.id);
console.log(`Status: ${retrieved.status}`); var retrieved = await client.Beta.Sessions.Retrieve(session.ID);
Console.WriteLine($"Status: {retrieved.Status.Raw()}"); retrieved, err := client.Beta.Sessions.Get(ctx, session.ID, juglow.BetaSessionGetParams{})
if err != nil {
panic(err)
}
fmt.Printf("Status: %s\n", retrieved.Status) var retrieved = client.beta().sessions().retrieve(session.id());
IO.println("Status: " + retrieved.status()); $retrieved = $client->beta->sessions->retrieve($session->id);
echo "Status: {$retrieved->status}\n"; retrieved = client.beta.sessions.retrieve(session.id)
puts "Status: #{retrieved.status}"Mendaftar sesi
Hasil dari GET /v1/sessions dipaginasi. Gunakan parameter query limit untuk mengontrol ukuran halaman. Setiap respons menyertakan kursor next_page; teruskan sebagai parameter page pada permintaan berikutnya untuk mengambil halaman selanjutnya. next_page bernilai null ketika tidak ada hasil lagi.
Untuk kembali satu halaman, teruskan prev_page sebagai parameter page. prev_page bernilai null ketika Anda berada di halaman pertama.
Kursor page bersifat opaque dan mengodekan order dari permintaan yang menghasilkannya. Parameter query order menetapkan arah pengurutan hasil, asc atau desc berdasarkan waktu pembuatan; nilai default-nya adalah desc (terbaru lebih dulu). Menggunakan kembali kursor dengan order yang berbeda akan mengembalikan kesalahan 400, begitu pula mengubah filter created_at sehingga mengecualikan posisi kursor. Parameter query lainnya, termasuk filter-filter yang tersisa dan limit, dapat berubah di antara permintaan yang dipaginasi. Untuk field paginasi yang digunakan bersama di seluruh endpoint daftar, lihat Paginasi.
first_page=$(curl -sS --fail-with-body \
"https://haijun.my.id/v1/sessions?agent_id=$AGENT_ID&limit=1" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "juglow-beta: managed-agents-2026-04-01")
jq '{prev_page, next_page}' <<< "$first_page" # prev_page is null on the first page
next_cursor=$(jq -r '.next_page' <<< "$first_page")
second_page=$(curl -sS --fail-with-body \
"https://haijun.my.id/v1/sessions?agent_id=$AGENT_ID&limit=1&page=$next_cursor" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "juglow-beta: managed-agents-2026-04-01")
prev_cursor=$(jq -r '.prev_page' <<< "$second_page")
curl -sS --fail-with-body \
"https://haijun.my.id/v1/sessions?agent_id=$AGENT_ID&limit=1&page=$prev_cursor" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "juglow-beta: managed-agents-2026-04-01" \
| jq '{prev_page, next_page}' # --format raw mengembalikan satu amplop halaman dengan kursor prev_page dan
# next_page-nya; output default melakukan paginasi otomatis dan hanya mengeluarkan sesi.
cursors=$(ant beta:sessions list \
--agent-id "$AGENT_ID" \
--limit 1 \
--format raw \
--transform '{prev_page,next_page}')
printf '%s\n' "$cursors"
# Teruskan kursor next_page kembali sebagai --page untuk mengambil halaman berikutnya.
NEXT_PAGE=$(jq -r '.next_page' <<< "$cursors")
ant beta:sessions list \
--agent-id "$AGENT_ID" \
--limit 1 \
--page "$NEXT_PAGE" \
--format raw \
--transform '{prev_page,next_page}'
# Teruskan prev_page dari respons itu sebagai --page untuk kembali dengan cara yang sama. # Setel `limit` rendah agar hasil mencakup lebih dari satu halaman.
first_page = client.beta.sessions.list(limit=1, agent_id=agent.id)
# `prev_page` bernilai None di halaman pertama; `next_page` bernilai None di halaman terakhir.
print(f"prev_page: {first_page.prev_page}")
print(f"next_page: {first_page.next_page}")
# Teruskan kembali `next_page` sebagai `page` untuk mengambil halaman berikutnya.
second_page = client.beta.sessions.list(
limit=1, agent_id=agent.id, page=first_page.next_page
)
for listed_session in second_page.data:
print(f"{listed_session.id}: {listed_session.status}")
# Teruskan kembali `prev_page` sebagai `page` untuk kembali ke halaman sebelumnya.
previous_page = client.beta.sessions.list(
limit=1, agent_id=agent.id, page=second_page.prev_page
)
for listed_session in previous_page.data:
print(f"{listed_session.id}: {listed_session.status}")
# Untuk iterasi maju saja, objek halaman juga dapat diiterasi secara langsung. const firstPage = await client.beta.sessions.list({ limit: 1, agent_id: agent.id });
// prev_page bernilai null pada halaman pertama; next_page terisi saat masih ada sesi lain.
console.log(`prev_page: ${firstPage.prev_page}`);
console.log(`next_page: ${firstPage.next_page}`);
// Teruskan next_page sebagai kursor `page` untuk mengambil halaman kedua.
const secondPage = await client.beta.sessions.list({
limit: 1,
agent_id: agent.id,
page: firstPage.next_page
});
for (const listedSession of secondPage.data) {
console.log(`Page 2 has ${listedSession.id}: ${listedSession.status}`);
}
// Teruskan kursor prev_page dari halaman kedua untuk kembali ke halaman pertama.
const previousPage = await client.beta.sessions.list({
limit: 1,
agent_id: agent.id,
page: secondPage.prev_page
});
for (const listedSession of previousPage.data) {
console.log(`Back on page 1: ${listedSession.id} is ${listedSession.status}`);
}
// Untuk iterasi maju saja, objek page juga dapat diiterasi langsung. // SessionListPage yang dikembalikan `List` mengekspos item-itemnya tetapi tidak
// kursor paginasinya. Untuk membaca `prev_page` / `next_page`, deserialisasi respons
// mentahnya ke SessionListPageResponse sebagai gantinya.
using var page1Response = await client.Beta.Sessions.WithRawResponse.List(
new SessionListParams { Limit = 1, AgentID = agent.ID }
);
var page1 = await page1Response.Deserialize<SessionListPageResponse>();
Console.WriteLine($"prev_page: {page1.PrevPage ?? "null"}");
Console.WriteLine($"next_page: {page1.NextPage ?? "null"}");
// Maju: berikan `next_page` dari halaman 1 sebagai kursor `page`.
using var page2Response = await client.Beta.Sessions.WithRawResponse.List(
new SessionListParams { Limit = 1, AgentID = agent.ID, Page = page1.NextPage }
);
var page2 = await page2Response.Deserialize<SessionListPageResponse>();
foreach (var listedSession in page2.Data ?? [])
{
Console.WriteLine($"Page 2: {listedSession.ID}: {listedSession.Status.Raw()}");
}
// Mundur: berikan `prev_page` dari halaman 2 sebagai kursor `page` yang sama.
using var previousPageResponse = await client.Beta.Sessions.WithRawResponse.List(
new SessionListParams { Limit = 1, AgentID = agent.ID, Page = page2.PrevPage }
);
var previousPage = await previousPageResponse.Deserialize<SessionListPageResponse>();
foreach (var listedSession in previousPage.Data ?? [])
{
Console.WriteLine($"Back to page 1: {listedSession.ID}: {listedSession.Status.Raw()}");
}
// Untuk iterasi maju saja, (await client.Beta.Sessions.List(...)).Paginate() mengembalikan IAsyncEnumerable yang otomatis mengikuti next_page. // Halaman 1: prev_page kosong karena tidak ada yang mendahului halaman pertama.
firstPage, err := client.Beta.Sessions.List(ctx, juglow.BetaSessionListParams{
AgentID: juglow.String(agent.ID),
Limit: juglow.Int(1),
})
if err != nil {
panic(err)
}
fmt.Printf("Page 1 prev_page: %q\n", firstPage.PrevPage)
fmt.Printf("Page 1 next_page: %q\n", firstPage.NextPage)
// Maju: berikan next_page sebagai kursor Page untuk mengambil halaman 2.
secondPage, err := client.Beta.Sessions.List(ctx, juglow.BetaSessionListParams{
AgentID: juglow.String(agent.ID),
Limit: juglow.Int(1),
Page: juglow.String(firstPage.NextPage),
})
if err != nil {
panic(err)
}
for _, listedSession := range secondPage.Data {
fmt.Printf("Page 2: %s: %s\n", listedSession.ID, listedSession.Status)
}
// Kembali: prev_page halaman 2 adalah kursor untuk halaman sebelumnya.
previousPage, err := client.Beta.Sessions.List(ctx, juglow.BetaSessionListParams{
AgentID: juglow.String(agent.ID),
Limit: juglow.Int(1),
Page: juglow.String(secondPage.PrevPage),
})
if err != nil {
panic(err)
}
for _, listedSession := range previousPage.Data {
fmt.Printf("Back to page 1: %s: %s\n", listedSession.ID, listedSession.Status)
}
// Untuk iterasi maju saja, gunakan ListAutoPaging agar next_page diikuti otomatis. var params = SessionListParams.builder()
.agentId(agent.id())
.limit(1)
.build();
var firstPage = client.beta().sessions().list(params);
for (var listedSession : firstPage.data()) {
IO.println(listedSession.id() + ": " + listedSession.status());
}
// prev_page adalah Optional kosong pada halaman pertama; next_page menunjuk ke halaman 2.
IO.println("prev_page: " + firstPage.response().prevPage());
IO.println("next_page: " + firstPage.response().nextPage());
// Maju dengan meneruskan next_page sebagai kursor halaman.
var nextCursor = firstPage.response().nextPage().orElseThrow();
var secondPage = client.beta().sessions().list(params.toBuilder().page(nextCursor).build());
// Kembali dengan meneruskan prev_page sebagai kursor halaman yang sama.
var prevCursor = secondPage.response().prevPage().orElseThrow();
var previousPage = client.beta().sessions().list(params.toBuilder().page(prevCursor).build());
// Kembali ke halaman pertama, jadi prev_page kosong lagi.
IO.println("prev_page: " + previousPage.response().prevPage());
// Untuk iterasi maju saja, page.autoPager() mengembalikan Iterable yang otomatis mengikuti next_page. // Halaman 1: prevPage bernilai null karena tidak ada yang mendahului halaman pertama.
$firstPage = $client->beta->sessions->list(agentID: $agent->id, limit: 1);
echo 'Page 1 prev_page: ' . ($firstPage->prevPage ?? 'null') . "\n";
echo 'Page 1 next_page: ' . ($firstPage->nextPage ?? 'null') . "\n";
// Maju: kirim kembali nextPage sebagai kursor `page` untuk mengambil halaman 2.
$secondPage = $client->beta->sessions->list(
agentID: $agent->id,
limit: 1,
page: $firstPage->nextPage,
);
foreach ($secondPage->getItems() as $listedSession) {
echo "Page 2: {$listedSession->id}: {$listedSession->status}\n";
}
// Mundur: prevPage halaman 2 adalah kursor untuk halaman sebelumnya.
$previousPage = $client->beta->sessions->list(
agentID: $agent->id,
limit: 1,
page: $secondPage->prevPage,
);
foreach ($previousPage->getItems() as $listedSession) {
echo "Back to page 1: {$listedSession->id}: {$listedSession->status}\n";
}
// Untuk iterasi maju saja, $page->pagingEachItem() menghasilkan setiap sesi di semua halaman. first_page = client.beta.sessions.list(agent_id: agent.id, limit: 1)
first_page.data.each do |listed_session|
puts "#{listed_session.id}: #{listed_session.status}"
end
# `prev_page` bernilai nil pada halaman pertama. Kursor halaman berikutnya diekspos sebagai
# `next_page_` (garis bawah di akhir) karena `next_page` biasa adalah metode helper
# yang mengambil objek halaman berikutnya untuk Anda.
puts "prev_page: #{first_page.prev_page.inspect}"
puts "next_page: #{first_page.next_page_.inspect}"
# Kirimkan salah satu kursor kembali sebagai `page` untuk menelusuri daftar di kedua arah.
second_page = client.beta.sessions.list(
agent_id: agent.id,
limit: 1,
page: first_page.next_page_
)
back_to_first = client.beta.sessions.list(
agent_id: agent.id,
limit: 1,
page: second_page.prev_page
)
back_to_first.data.each do |listed_session|
puts "#{listed_session.id}: #{listed_session.status}"
end
# Untuk iterasi maju saja, page.auto_paging_each otomatis mengikuti next_page.Mengarsipkan sesi
Arsipkan sesi untuk mencegah event baru dikirim sambil tetap mempertahankan riwayatnya. Sesi yang berstatus running tidak dapat diarsipkan; untuk mengarsipkannya, kirimkan event user.interrupt secara tersendiri dan tunggu hingga sesi menjadi idle.
curl -fsSL -X POST "https://haijun.my.id/v1/sessions/$SESSION_ID/archive" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "juglow-beta: managed-agents-2026-04-01" ant beta:sessions archive \
--session-id "$SESSION_ID" client.beta.sessions.archive(session.id) await client.beta.sessions.archive(session.id); await client.Beta.Sessions.Archive(session.ID); _, err = client.Beta.Sessions.Archive(ctx, session.ID, juglow.BetaSessionArchiveParams{})
if err != nil {
panic(err)
} client.beta().sessions().archive(session.id()); $client->beta->sessions->archive($session->id); client.beta.sessions.archive(session.id)Menghapus sesi
Hapus sesi untuk menghilangkan secara permanen catatan, event, dan sandbox terkaitnya. Sesi yang berstatus running tidak dapat dihapus; untuk menghapusnya, kirimkan event user.interrupt secara tersendiri dan tunggu hingga sesi menjadi idle.
Memory store, vault, track, environment, dan agen adalah sumber daya independen dan tidak terpengaruh oleh penghapusan sesi. File yang Anda unggah melalui Files API juga tidak terpengaruh, tetapi file yang dihasilkan oleh sesi itu sendiri terikat pada sesi tersebut dan dihapus secara permanen bersama sistem file-nya. Unduh apa pun yang perlu Anda simpan sebelum menghapus sesi. File output yang ditulis di akhir giliran terakhir dapat memerlukan beberapa detik setelah sesi menjadi idle untuk muncul di daftar file sesi, jadi periksa terlebih dahulu bahwa file yang Anda harapkan sudah terdaftar.
curl -fsSL -X DELETE "https://haijun.my.id/v1/sessions/$SESSION_ID" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "juglow-beta: managed-agents-2026-04-01" ant beta:sessions delete \
--session-id "$SESSION_ID" client.beta.sessions.delete(session.id) await client.beta.sessions.delete(session.id); await client.Beta.Sessions.Delete(session.ID); _, err = client.Beta.Sessions.Delete(ctx, session.ID, juglow.BetaSessionDeleteParams{})
if err != nil {
panic(err)
} client.beta().sessions().delete(session.id()); $client->beta->sessions->delete($session->id); client.beta.sessions.delete(session.id)