`agent.session` Tool Allowlist Parameters Do Not Restrict the Host Tool Set

Summary

I attempted to restrict the tools available to an Agent session according to the official Anna developer documentation. The intended policy was to allow only fs_read_file and prevent access to fs_write_file.

After two rounds of testing in a local anna-app dev environment, the session still received the complete Host tool set and successfully executed fs_write_file, even though it was not included in the allowlist.

The session reported:

{
  "inherit_host_tools": true,
  "granted_tools": ["*"]
}

The subsequent fs_write_file call completed successfully. It is therefore unclear whether quotaCaps.inherit_host_tools, session-level quotaCaps.allowed_tools, or run-level allowed_tools is currently enforced in this environment.

Expected Behavior Based on the Official Documentation

I reviewed the official documentation index at https://staging.anna.partners/llms.txt, as well as the following related pages:

My understanding of the documented behavior is as follows:

  1. agent.session.create can restrict a session through quotaCaps:

    anna.agent.session.create({
      submode: "auto",
      quotaCaps: {
        inherit_host_tools: false,
        allowed_tools: ["fs_read_file"],
      },
    });
    
  2. agent.session.run can restrict an individual run through allowed_tools:

    anna.agent.session.run({
      app_session_uuid,
      content,
      allowed_tools: ["fs_read_file"],
    });
    
  3. manifest.ui.host_api.agent.tools should define the App-level tool boundary.

  4. The documentation also states that when a session inherits the Host tool set with inherit_host_tools: true, per-run allowed_tools does not further narrow the inherited tool surface.

There appears to be some inconsistency between the documentation pages. The detailed agent.session.create signature primarily lists numeric quotaCaps fields, while other pages explicitly describe inherit_host_tools and allowed_tools. This report is intended to clarify the actual support status of these fields in the current staging and development implementations.

Local Test Environment

  • Test command: anna-app dev
  • Test App: examples/test-session-app
  • Runtime: Anna App Runtime
  • CLI and schema versions: local @anna-ai/cli 0.1.40 and @anna-ai/app-schema 0.18.0
  • Invocation method: low-level raw RPC calls
    • anna.agent.session.create(...)
    • anna.agent.session.run(...)
    • anna.agent.session.delete(...)
  • Test objective: allow the session to read files but prevent it from writing files

Manifest Configuration

Both test runs used the same App manifest:

{
  "schema": 2,
  "permissions": [],
  "required_executas": [],
  "optional_executas": [],
  "ui": {
    "host_api": {
      "agent": {
        "session": {
          "auto": true,
          "fixed": null
        },
        "tools": []
      }
    }
  }
}

The complete manifest does not grant additional access through other Host API namespaces. The portion directly relevant to this issue is:

"agent": {
  "session": {
    "auto": true,
    "fixed": null
  },
  "tools": []
}

Test 1: Applying the Tool Restriction in session.create

Session creation code

const raw = await anna.agent.session.create({
  submode: "auto",
  quotaCaps: {
    inherit_host_tools: false,
    allowed_tools: ["fs_read_file"],
  },
});

Run code

The first test did not repeat the tool allowlist in run:

const runResult = await anna.agent.session.run({
  app_session_uuid: id,
  content,
});

Result

The session returned the following run_meta frame:

{
  "submode": "auto",
  "inherit_host_tools": true,
  "granted_tools": ["*"]
}

I then performed two operations:

  1. fs_read_file successfully read a file.
  2. fs_write_file successfully modified a file.

Although fs_write_file was not included in the requested allowlist, the server returned a successful result:

{
  "success": true,
  "data": {
    "path": "/Users/leyouming/anna-workspace/.docs/tmp.txt",
    "size": 34
  }
}

This indicates that the create-level inherit_host_tools: false and allowed_tools: ["fs_read_file"] settings did not produce the expected restriction in this environment.

Test 2: Applying the Tool Restriction Only in session.run

To distinguish session creation behavior from per-run behavior, the second test restored session creation to its default configuration and passed the allowlist only to the individual run.

Session creation code

const raw = await anna.agent.session.create({
  submode: "auto",
});

Run code

const runResult = await anna.agent.session.run({
  app_session_uuid: id,
  content,
  allowed_tools: ["fs_read_file"],
});

Result

The second test also returned:

{
  "submode": "auto",
  "inherit_host_tools": true,
  "granted_tools": ["*"]
}

I then asked the Agent to modify a file. The Agent invoked:

fs_write_file

The tool call completed successfully:

{
  "success": true,
  "data": {
    "path": "/Users/leyouming/anna-workspace/.docs/tmp.txt",
    "size": 52
  }
}

The run-level allowed_tools: ["fs_read_file"] setting therefore did not prevent fs_write_file from executing.

Expected vs. Actual Behavior

Item Expected Actual
Create-level inherit_host_tools false true
Create-level allowed_tools Only fs_read_file is available granted_tools: ["*"] is returned
Run-level allowed_tools Only fs_read_file is available for the run fs_write_file executes successfully
Host tool set File-writing tools should not be available The complete Host tool set remains available

Possible Causes

I cannot determine which layer is responsible for the behavior. Could you please confirm whether one of the following explanations applies?

  1. The server-side session minting logic does not process the tool-scope fields

    The server may not read quotaCaps.inherit_host_tools, or the requested false value may be overwritten by a default value of true when the request is intersected with the user’s grant.

  2. quotaCaps.allowed_tools may be documented but not yet implemented by the current API

    The returned granted_tools: ["*"] indicates that the session did not receive a Sandbox tool surface.

  3. Run-level allowed_tools is intentionally ignored for sessions that inherit Host tools

    The official Platform tools page states that a session inheriting the Host tool set cannot be narrowed through per-run allowed_tools. The observed result is consistent with that statement.

  4. The development grant may enable the complete Host tool set by default

    The grant used by anna-app dev may force inherit_host_tools: true, preventing an App from creating a genuine Sandbox session in the development environment.

  5. Manifest-level agent.tools: [] does not restrict inherited Host tools

    The manifest declares an empty agent.tools array, but the session still receives granted_tools: ["*"]. It would be helpful to confirm whether this is the expected inheritance behavior or whether the manifest ACL is not being applied on this path.

Questions

  1. Are quotaCaps.inherit_host_tools and quotaCaps.allowed_tools on agent.session.create currently supported in the staging environment?
  2. If the user’s grant permits Host tool inheritance, can an App still create a Sandbox session by explicitly passing inherit_host_tools: false?
  3. Is agent.session.run.allowed_tools supported only for Sandbox sessions?
  4. Can fs_read_file and fs_write_file be controlled independently through the Sandbox registry?
  5. What is the recommended way for an App to create an Agent session that can read files but is explicitly prohibited from writing them?

Conclusion

In the current local anna-app dev environment, neither of the following configurations achieved the intended policy of allowing fs_read_file while preventing fs_write_file:

  • Create-level restriction: quotaCaps.inherit_host_tools: false together with quotaCaps.allowed_tools: ["fs_read_file"]
  • Run-level restriction: allowed_tools: ["fs_read_file"]

In both tests, the session received the complete Host tool set and successfully executed fs_write_file. I would appreciate clarification on whether this behavior is caused by an implementation issue, development-specific grant behavior, or documentation that does not yet match the currently deployed API version.

Hi @HappyLight! :waving_hand:

Thank you so much for this wonderfully detailed report — the two isolated test rounds and the expected-vs-actual table made it very easy for us to reproduce and pinpoint the issue. This is exactly the kind of feedback that makes the platform better. :yellow_heart:

TL;DR — Confirmed & Fixed :white_check_mark:

You were right: in the anna-app dev environment, quotaCaps.inherit_host_tools: false and quotaCaps.allowed_tools were not being enforced. This has been fixed and deployed to staging as of 2026-08-04.

To pick up the fix: upgrade your CLI to @anna-ai/cli ≥ 0.1.45 and restart anna-app dev. :rocket:

What was wrong :bug:

  1. The dev session mint path dropped inherit_host_tools from the requested quotaCaps, so the session always fell back to the dev grant’s default (true) — a real sandbox session could never be created in dev. Your Possible Cause #1 was spot on. :bullseye:
  2. The dev grant’s tool allowlist was effectively empty, so even a correctly-passed sandbox request would have yielded no usable tools.
  3. The sandbox tool registry was very small at the time — file tools weren’t in it, so a “read-only files” policy simply couldn’t be expressed. Your Possible Cause #5 was also correct.

What’s fixed & improved :sparkles:

  • :white_check_mark: quotaCaps.inherit_host_tools: false is now honored on the dev path (it already worked in production).
  • :white_check_mark: quotaCaps.allowed_tools now intersects against a real sandbox tool catalog.
  • :white_check_mark: The sandbox registry has been expanded to 23 platform tools, including the full fs_* family with independent read/write granularity, exec_*, browser tools, and web_search — so yes, fs_read_file and fs_write_file can now be controlled separately! :tada:
  • :white_check_mark: Reference docs and the CLI’s local session catalog have been synced to match.

Answers to your questions :speech_balloon:

  1. Are inherit_host_tools / allowed_tools supported on session.create? Yes — fully supported now, in both dev and staging.
  2. Can an App opt into a sandbox session even if the user grant allows inheritance? Yes — explicitly pass inherit_host_tools: false.
  3. Is run-level allowed_tools only for sandbox sessions? Correct, and this is by design — when a session inherits the full Host tool set, per-run allowed_tools does not narrow it. Your Possible Cause #3 matched the docs exactly.
  4. Independent control of fs_read_file / fs_write_file? Yes, as of this fix. :white_check_mark:
  5. Recommended “read but don’t write” recipe:
const session = await anna.agent.session.create({
  submode: "auto",
  quotaCaps: {
    inherit_host_tools: false,
    allowed_tools: ["fs_read_file"],
  },
});

The run_meta frame should now report inherit_host_tools: false with granted_tools: ["fs_read_file"], and any fs_write_file attempt will be rejected. :locked:

Please give it a try with the latest CLI and let us know if anything still looks off — happy building! :hammer_and_wrench::dizzy:

Follow-up: fs_read_file Still Not Granted After Upgrading the CLI and Applying the Official Sandbox Allowlist Configuration

Thank you for confirming and fixing the issue where the anna-app dev path did not correctly honor quotaCaps.inherit_host_tools and quotaCaps.allowed_tools.

Following your recommendation, we upgraded the CLI, redesigned the test to isolate the create-level tool restriction, and added the manifest tool declaration described in the current documentation and the official anna-app-llm-demo example. However, after fully restarting anna-app dev and creating a brand-new session, fs_read_file still does not appear in the resolved tool set.

The current result is:

{
  "inherit_host_tools": false,
  "granted_tools": [],
  "warnings": [
    {
      "code": "NO_TOOLS_AVAILABLE"
    }
  ]
}

In other words, inherit_host_tools: false is now honored, but the requested fs_read_file tool resolves to an empty tool set. The complete test process is described below.

Test objective

We want to create an Agent Session that can read local files while being explicitly prohibited from writing files:

  • Allowed: fs_read_file
  • Denied: fs_write_file
  • Do not inherit the complete Host tool set
  • Do not pass allowed_tools again in session.run, so that we test create-level quotaCaps in isolation

Test environment

  • Operating system: macOS
  • Test mode: local anna-app dev
  • App: examples/test-session-app
  • Anna App Runtime: the iframe connects to the Host API through AnnaAppRuntime.connect()
  • Invocation style: low-level raw RPC
    • anna.agent.session.create(...)
    • anna.agent.session.run(...)
    • anna.agent.session.delete(...)
  • @anna-ai/cli: 0.1.45
  • @anna-ai/app-schema: 0.19.0
  • @anna-ai/app-runtime: 0.15.0
  • Manifest schema: 2

The CLI version was confirmed with:

anna-app --version

which returned:

0.1.45

anna-app validate --strict also passed.

Phase 1: Baseline with the original call pattern

The original test App created a session with the default configuration:

await anna.agent.session.create({
  submode: "auto",
});

It then passed the allowlist only to an individual run:

await anna.agent.session.run({
  app_session_uuid,
  content,
  allowed_tools: ["fs_read_file"],
});

The resulting run_meta was:

{
  "inherit_host_tools": true,
  "granted_tools": ["*"]
}

The Agent then successfully invoked fs_write_file and modified the file.

This matches the explanation in the previous forum reply: when a session inherits the full Host tool set, run-level allowed_tools does not further narrow the surface. We therefore changed the test so that the restriction is applied only at session.create time.

Phase 2: Applying the recommended session.create configuration

After upgrading @anna-ai/cli to 0.1.45, we changed the create input to:

const SESSION_CREATE_INPUT = {
  submode: "auto",
  quotaCaps: {
    inherit_host_tools: false,
    allowed_tools: ["fs_read_file"],
  },
};

const raw = await anna.agent.session.create(SESSION_CREATE_INPUT);

We also removed allowed_tools entirely from session.run so that the create-level and run-level policies would not interfere with each other:

await anna.agent.session.run({
  app_session_uuid,
  content,
});

The actual RPC request was:

→ req agent.session.create
{
  "submode": "auto",
  "quotaCaps": {
    "inherit_host_tools": false,
    "allowed_tools": ["fs_read_file"]
  }
}

The session.run request confirmed that no allowed_tools field was sent:

→ req agent.session.run
{
  "app_session_uuid": "aps_…",
  "content": "Please read the specified file and then try to append one test line to it"
}

Phase 3: Adding the tool declaration to the manifest

During the first create-level test, agent.tools was still empty in the manifest:

"agent": {
  "session": {
    "auto": true,
    "fixed": null
  },
  "tools": []
}

That test returned:

{
  "inherit_host_tools": false,
  "granted_tools": [],
  "warnings": [
    {
      "code": "NO_TOOLS_AVAILABLE"
    }
  ]
}

We then reviewed the following official documentation:

  • App-Side LLM & Agent API
  • agent.* Host API reference
  • Platform tools — the agent-session tool universe

The documentation describes the sandbox tool surface as the following intersection:

AppToolRegistry.public_set
∩ manifest.ui.host_api.agent.tools
∩ user grant
∩ quotaCaps.allowed_tools

We also inspected the official anna-app-llm-demo example. It declares a platform tool name directly in the manifest:

"agent": {
  "session": { "auto": true },
  "tools": ["web_search"]
}

Based on that example, we changed the test App’s manifest to:

{
  "schema": 2,
  "permissions": [],
  "required_executas": [],
  "optional_executas": [],
  "ui": {
    "host_api": {
      "llm": ["complete"],
      "agent": {
        "session": {
          "auto": true,
          "fixed": null
        },
        "tools": ["fs_read_file"]
      },
      "window": ["set_title"]
    }
  }
}

Keeping permissions empty was intentional. The current agent.* reference states that Agent Session ACL checks read manifest.ui.host_api.agent, rather than the top-level permissions[] field.

After changing the manifest, we ran:

anna-app validate --strict

Validation passed. We then fully stopped the original dev process and started it again:

cd examples/test-session-app
anna-app dev

We reopened the App and created a completely new session without reusing the previous app_session_uuid.

Final reproduction after a full restart

The restarted session.create request was:

→ req agent.session.create
{
  "submode": "auto",
  "quotaCaps": {
    "inherit_host_tools": false,
    "allowed_tools": ["fs_read_file"]
  }
}

The session.create response was:

{
  "app_session_uuid": "aps_…",
  "expires_in": 600,
  "submode": "auto",
  "fixed_client_id": null,
  "granted_tools": []
}

One additional observation is that the create response did not include the inherit_host_tools field documented in the reference, although the subsequent run_meta frame did include it.

We then sent a run that explicitly asked the Agent to read a file and attempt a write:

Please read /Users/<user>/anna-workspace/.docs/tmp.txt,
then append one Session test line after the last line.

The authoritative run_meta frame was:

{
  "event": "run_meta",
  "run_id": "…",
  "app_session_uuid": "aps_…",
  "submode": "auto",
  "inherit_host_tools": false,
  "granted_tools": [],
  "warnings": [
    {
      "code": "NO_TOOLS_AVAILABLE",
      "message": "This agent session resolved ZERO executable tools: it cannot read/write local files, browse, or run commands. Any side effects claimed in the model output (e.g. 'changed_files') will NOT have happened. Grant tools to this app (inherit_host_tools / allowed_tools) or use llm.complete for text-only generation."
    }
  ]
}

No fs_read_file or fs_write_file tool call appeared afterwards. The run ended with:

{
  "error_type": "empty_completion",
  "error": "Agent run completed without producing any output (no assistant message, no tool calls)."
}

The target file remained unchanged, confirming that no file side effect occurred in this run.

Expected vs. actual

Item Expected Actual
CLI version @anna-ai/cli >= 0.1.45 0.1.45
create-level inherit_host_tools false false — this part works
manifest agent.tools Contains fs_read_file ['fs_read_file']
create-level allowed_tools ['fs_read_file'] ['fs_read_file']
run-level allowed_tools Omitted to avoid interference Omitted
Final granted_tools ['fs_read_file'] []
fs_read_file Executable Unavailable; no tool call occurred
fs_write_file Unavailable and should be rejected Could not be tested because the entire tool set was empty
Run result Read succeeds, write is rejected, normal assistant output is returned NO_TOOLS_AVAILABLE, followed by empty_completion

Comparison with the official example

The official anna-app-llm-demo uses this manifest declaration:

"agent": {
  "session": { "auto": true },
  "tools": ["web_search"]
}

When inherit is disabled, it builds the create-level configuration as:

quotaCaps = {
  inherit_host_tools: false,
  allowed_tools: tools,
};

await anna.agent.session({
  submode: "auto",
  quotaCaps,
});

Our test uses the same structure, replacing web_search with fs_read_file, which is explicitly listed in the official Sandbox registry, and using the equivalent raw session.create API.

Therefore, based on the current documentation and official example, the expected resolved surface is:

{
  "inherit_host_tools": false,
  "granted_tools": ["fs_read_file"]
}

The actual result is still an empty set.

Questions for clarification

  1. Can fs_read_file be declared directly in manifest.ui.host_api.agent.tools, in the same way as the official example declares web_search?
  2. Does anna-app dev synchronize the local manifest’s agent.tools into the dev App grant used when minting a real Agent Session?
  3. Does the current result mean that fs_read_file is blocked by the user grant? If so, where can this grant be enabled or refreshed in local development?
  4. After upgrading the CLI and restarting anna-app dev, is an additional login, dev-grant reset, or permission synchronization step required?
  5. Is it expected that session.create returns granted_tools: [] but omits the documented inherit_host_tools field?
  6. For this scenario, should anna.agent.session.catalog() return fs_read_file with blocked_by: "manifest" or blocked_by: "user_grant"? Should we use the catalog result as the next diagnostic step?

Conclusion

After upgrading to @anna-ai/cli 0.1.45, quotaCaps.inherit_host_tools: false is honored on the local anna-app dev path. That part is consistent with the fix described in the previous reply.

However, even with all of the following in place:

  • manifest declares agent.tools: ["fs_read_file"];
  • create request declares allowed_tools: ["fs_read_file"];
  • run request omits allowed_tools;
  • anna-app dev is fully restarted;
  • a brand-new Agent Session is created;

the final result is still granted_tools: [] with NO_TOOLS_AVAILABLE. We cannot obtain the expected sandbox session that can read files but cannot write them.

We can provide the complete RPC log if useful, or add agent.session.catalog() to the test App and follow up with the per-tool eligible / blocked_by results.