diff --git a/tests/test_tools/test_token_budget.py b/tests/test_tools/test_token_budget.py
new file mode 100644
index 0000000..8e49d81
--- /dev/null
+++ b/tests/test_tools/test_token_budget.py
@@ -0,0 +1,52 @@
+"""Integration test: combined multi-tool workflow stays within token budget."""
+
+from __future__ import annotations
+
+import json
+
+import pytest
+
+from godotiq.session import GodotIQSession
+from godotiq.tools.memory import _build_project_summary, _build_file_context
+from godotiq.tools.code import _build_signal_map, _build_dependency_graph, _build_validate
+from godotiq.tools.spatial import _build_scene_map, _build_spatial_audit
+from godotiq.tools.assets import _build_asset_registry
+
+
+def _output_size(result: dict) -> int:
+    """Return JSON-serialized character count of a result dict."""
+    return len(json.dumps(result, default=str, ensure_ascii=False))
+
+
+class TestTokenBudget:
+    """Integration tests verifying combined tool output stays within budget."""
+
+    def test_combined_workflow_under_30000_chars(self, session: GodotIQSession) -> None:
+        """A typical multi-tool workflow stays under 30,000 chars total."""
+        total = 0
+        total += _output_size(_build_project_summary(session, detail="brief"))
+        total += _output_size(_build_scene_map(session, scene_path="res://scenes/main.tscn", detail="normal"))
+        total += _output_size(_build_asset_registry(session, detail="brief"))
+        total += _output_size(_build_spatial_audit(session, scene="res://scenes/main.tscn", detail="brief"))
+        total += _output_size(_build_signal_map(session, detail="brief"))
+        assert total < 30_000, f"Combined workflow output {total} chars exceeds 30,000"
+
+    def test_all_offline_tools_default_within_normal(self, session: GodotIQSession) -> None:
+        """Every offline tool at default detail produces output under 10,000 chars."""
+        results = {
+            "project_summary": _build_project_summary(session),
+            "scene_map": _build_scene_map(session, scene_path="res://scenes/main.tscn"),
+            "asset_registry": _build_asset_registry(session),
+            "spatial_audit": _build_spatial_audit(session, scene="res://scenes/main.tscn"),
+            "signal_map": _build_signal_map(session),
+            "dependency_graph": _build_dependency_graph(
+                session, file_path="res://scripts/autoloads/economy_manager.gd"
+            ),
+            "validate": _build_validate(session),
+            "file_context": _build_file_context(
+                session, file_path="res://scripts/autoloads/economy_manager.gd"
+            ),
+        }
+        for tool_name, result in results.items():
+            size = _output_size(result)
+            assert size < 10_000, f"{tool_name} default output {size} chars exceeds 10,000"
