List files
curl --request POST \
--url https://agp.eu.hcompany.ai/api/v2/sessions/{session_id}/files/list_files \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"path": "<string>",
"max_entries": 123,
"modified_before": "<string>",
"name_after": "<string>"
}
'import requests
url = "https://agp.eu.hcompany.ai/api/v2/sessions/{session_id}/files/list_files"
payload = {
"path": "<string>",
"max_entries": 123,
"modified_before": "<string>",
"name_after": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
path: '<string>',
max_entries: 123,
modified_before: '<string>',
name_after: '<string>'
})
};
fetch('https://agp.eu.hcompany.ai/api/v2/sessions/{session_id}/files/list_files', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://agp.eu.hcompany.ai/api/v2/sessions/{session_id}/files/list_files",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'path' => '<string>',
'max_entries' => 123,
'modified_before' => '<string>',
'name_after' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://agp.eu.hcompany.ai/api/v2/sessions/{session_id}/files/list_files"
payload := strings.NewReader("{\n \"path\": \"<string>\",\n \"max_entries\": 123,\n \"modified_before\": \"<string>\",\n \"name_after\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://agp.eu.hcompany.ai/api/v2/sessions/{session_id}/files/list_files")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"path\": \"<string>\",\n \"max_entries\": 123,\n \"modified_before\": \"<string>\",\n \"name_after\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://agp.eu.hcompany.ai/api/v2/sessions/{session_id}/files/list_files")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"path\": \"<string>\",\n \"max_entries\": 123,\n \"modified_before\": \"<string>\",\n \"name_after\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"path": "<string>",
"files": [
{}
],
"truncated": true
}Sessions
List files
List the files on a cloud browser’s machine, such as what the agent downloaded.
POST
/
api
/
v2
/
sessions
/
{session_id}
/
files
/
list_files
List files
curl --request POST \
--url https://agp.eu.hcompany.ai/api/v2/sessions/{session_id}/files/list_files \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"path": "<string>",
"max_entries": 123,
"modified_before": "<string>",
"name_after": "<string>"
}
'import requests
url = "https://agp.eu.hcompany.ai/api/v2/sessions/{session_id}/files/list_files"
payload = {
"path": "<string>",
"max_entries": 123,
"modified_before": "<string>",
"name_after": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
path: '<string>',
max_entries: 123,
modified_before: '<string>',
name_after: '<string>'
})
};
fetch('https://agp.eu.hcompany.ai/api/v2/sessions/{session_id}/files/list_files', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://agp.eu.hcompany.ai/api/v2/sessions/{session_id}/files/list_files",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'path' => '<string>',
'max_entries' => 123,
'modified_before' => '<string>',
'name_after' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://agp.eu.hcompany.ai/api/v2/sessions/{session_id}/files/list_files"
payload := strings.NewReader("{\n \"path\": \"<string>\",\n \"max_entries\": 123,\n \"modified_before\": \"<string>\",\n \"name_after\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://agp.eu.hcompany.ai/api/v2/sessions/{session_id}/files/list_files")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"path\": \"<string>\",\n \"max_entries\": 123,\n \"modified_before\": \"<string>\",\n \"name_after\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://agp.eu.hcompany.ai/api/v2/sessions/{session_id}/files/list_files")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"path\": \"<string>\",\n \"max_entries\": 123,\n \"modified_before\": \"<string>\",\n \"name_after\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"path": "<string>",
"files": [
{}
],
"truncated": true
}Lists a directory on the machine hosting a cloud browser, newest first. Use it to see what the agent downloaded, then read a file out or write one in for the agent to use.
Returns the directory
Only the browser’s download directory (
path, its files, and truncated, true when the listing stopped at max_entries.
The
session_id here is the browser session id, not the agent session id from /api/v2/sessions. Each cloud browser runs in its own browser session, and the agent publishes that id on the events stream as a RunnerSessionEvent (data.runner_session_id) when it connects. An agent session id is answered with 404.~/Downloads) is reachable. Paths outside it, including the browser profile, are rejected.
Path parameters
string
required
The browser session id, from the session’s
RunnerSessionEvent.Request body
string
default:"~/Downloads"
Directory to list.
integer
default:"500"
Maximum number of entries to return. When the directory holds more,
truncated is true and the page ends at the oldest entry returned.string
Page cursor: the
modified_at of the last entry of the previous page. Always send it together with name_after.string
Page cursor: the
name of the last entry of the previous page. Modification times are not unique, so the name is what keeps files sharing one from being skipped.Response
string
The listed directory, resolved.
array
Entries, newest first. Each is
{ name, path, size_bytes, modified_at, is_dir }.boolean
true when the listing stopped at max_entries. Take modified_at and name from the last entry and send them as modified_before and name_after for the next page.Examples
curl -X POST https://agp.eu.hcompany.ai/api/v2/sessions/$BROWSER_SESSION_ID/files/list_files \
-H "Authorization: Bearer $HAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"path": "~/Downloads", "max_entries": 100}'
from hai_agents import Client
client = Client()
page = client.session_files.list_files(browser_session_id, path="~/Downloads", max_entries=100)
for entry in page.files:
print(entry.name, entry.size_bytes, entry.modified_at)
import { HaiAgentsClient } from "hai-agents";
const client = new HaiAgentsClient();
const page = await client.sessionFiles.listFiles({
sessionId: browserSessionId,
path: "~/Downloads",
maxEntries: 100,
});
for (const entry of page.files) {
console.log(entry.name, entry.sizeBytes, entry.modifiedAt);
}
Response
{
"path": "/home/hai/Downloads",
"files": [
{
"name": "invoice-2026-09.pdf",
"path": "/home/hai/Downloads/invoice-2026-09.pdf",
"size_bytes": 48213,
"modified_at": "2026-09-15T09:41:12Z",
"is_dir": false
}
],
"truncated": false
}
Page through a large directory
Pass the last entry’smodified_at and name back as the cursor until truncated is false:
Python
cursor = {}
while True:
page = client.session_files.list_files(browser_session_id, max_entries=100, **cursor)
handle(page.files)
if not page.truncated:
break
last = page.files[-1]
cursor = {"modified_before": last.modified_at, "name_after": last.name}
Was this page helpful?