diff --git a/func_adl/event_dataset.py b/func_adl/event_dataset.py
index 34d7a69..15ccd8f 100644
--- a/func_adl/event_dataset.py
+++ b/func_adl/event_dataset.py
@@ -20,7 +20,7 @@ class EventDataset(ObjectStream, ABC):
         # We participate in the AST parsing - as a node. This argument is used in a lookup
         # later on - so do not alter this in a subclass without understanding what is
         # going on!
-        self._ast = function_call('EventDataset', [ast.Constant(value=self)])
+        super().__init__(function_call('EventDataset', [ast.Constant(value=self)]))
 
     def __repr__(self):
         return f"'{self.__class__.__name__}'"
diff --git a/func_adl/object_stream.py b/func_adl/object_stream.py
index a1ae73e..7b72139 100644
--- a/func_adl/object_stream.py
+++ b/func_adl/object_stream.py
@@ -32,7 +32,16 @@ class ObjectStream:
         Initialize the stream with the ast that will produce this stream of objects.
         The user will almost never use this initializer.
         """
-        self._ast = the_ast
+        self._q_ast = the_ast
+
+    @property
+    def query_ast(self) -> ast.AST:
+        '''Return the query `ast` that this `ObjectStream` represents
+
+        Returns:
+            ast.AST: The python `ast` that is represented by this query
+        '''
+        return self._q_ast
 
     def SelectMany(self, func: Union[str, ast.Lambda]) -> 'ObjectStream':
         r"""
@@ -48,7 +57,7 @@ class ObjectStream:
         Returns:
             A new ObjectStream of the type of the elements.
         """
-        return ObjectStream(function_call("SelectMany", [self._ast, cast(ast.AST, parse_as_ast(func))]))
+        return ObjectStream(function_call("SelectMany", [self._q_ast, cast(ast.AST, parse_as_ast(func))]))
 
     def Select(self, f: Union[str, ast.Lambda]) -> 'ObjectStream':
         r"""
@@ -63,7 +72,7 @@ class ObjectStream:
 
             A new ObjectStream of the transformed elements.
         """
-        return ObjectStream(function_call("Select", [self._ast, cast(ast.AST, parse_as_ast(f))]))
+        return ObjectStream(function_call("Select", [self._q_ast, cast(ast.AST, parse_as_ast(f))]))
 
     def Where(self, filter) -> 'ObjectStream':
         r'''
@@ -77,7 +86,7 @@ class ObjectStream:
 
             A new ObjectStream that contains only elements that pass the filter function
         '''
-        return ObjectStream(function_call("Where", [self._ast, cast(ast.AST, parse_as_ast(filter))]))
+        return ObjectStream(function_call("Where", [self._q_ast, cast(ast.AST, parse_as_ast(filter))]))
 
     def AsPandasDF(self, columns=[]) -> 'ObjectStream':
         r"""
@@ -93,7 +102,7 @@ class ObjectStream:
         """
 
         # To get Pandas use the ResultPandasDF function call.
-        return ObjectStream(function_call("ResultPandasDF", [self._ast, as_ast(columns)]))
+        return ObjectStream(function_call("ResultPandasDF", [self._q_ast, as_ast(columns)]))
 
     def AsROOTTTree(self, filename, treename, columns=[]) -> 'ObjectStream':
         r"""
@@ -120,7 +129,7 @@ class ObjectStream:
             dataset.  The order of the files back is consistent for different queries on the same
             dataset.
         """
-        return ObjectStream(function_call("ResultTTree", [self._ast, as_ast(columns), as_ast(treename), as_ast(filename)]))
+        return ObjectStream(function_call("ResultTTree", [self._q_ast, as_ast(columns), as_ast(treename), as_ast(filename)]))
 
     def AsParquetFiles(self, filename: str, columns: Union[str, List[str]] = []) -> 'ObjectStream':
         '''Returns the sequence of items as a `parquet` file. Each item in the ObjectStream gets a separate
@@ -144,7 +153,7 @@ class ObjectStream:
             the backend - the data should be concatinated together to get a final result. The order of the files back
             is consistent for different queries on the same dataset.
         '''
-        return ObjectStream(function_call("ResultParquet", [self._ast, as_ast(columns), as_ast(filename)]))
+        return ObjectStream(function_call("ResultParquet", [self._q_ast, as_ast(columns), as_ast(filename)]))
 
     def AsAwkwardArray(self, columns=[]) -> 'ObjectStream':
         r'''
@@ -160,7 +169,7 @@ class ObjectStream:
 
             An `ObjectStream` with the `awkward` array data as its one and only element.
         '''
-        return ObjectStream(function_call("ResultAwkwardArray", [self._ast, as_ast(columns)]))
+        return ObjectStream(function_call("ResultAwkwardArray", [self._q_ast, as_ast(columns)]))
 
     def _get_executor(self, executor: Callable[[ast.AST], Awaitable[Any]] = None) -> Callable[[ast.AST], Awaitable[Any]]:
         r'''
@@ -177,7 +186,7 @@ class ObjectStream:
             return executor
 
         from .event_dataset import find_ed_in_ast
-        ed = find_ed_in_ast(self._ast)
+        ed = find_ed_in_ast(self._q_ast)
 
         return ed.execute_result_async
 
@@ -208,6 +217,6 @@ class ObjectStream:
         exe = self._get_executor(executor)
 
         # Run it
-        return await exe(self._ast)
+        return await exe(self._q_ast)
 
     value = make_sync(value_async)

add a ast property to ObjectStream for access.
diff --git a/tests/test_event_dataset.py b/tests/test_event_dataset.py
index 806ae84..d7743b8 100644
--- a/tests/test_event_dataset.py
+++ b/tests/test_event_dataset.py
@@ -1,5 +1,5 @@
 import ast
-from typing import Any
+from typing import Any, cast
 
 import pytest
 
@@ -20,7 +20,7 @@ class my_event(EventDataset):
 class my_event_extra_args(EventDataset):
     def __init__(self):
         super().__init__()
-        self._ast.args.append(ast.Str(s='hi'))
+        cast(ast.Call, self.query_ast).args.append(ast.Str(s='hi'))
 
     async def execute_result_async(self, a: ast.AST) -> Any:
         return 10
@@ -32,18 +32,18 @@ def test_can_create():
 
 def test_find_event_at_top():
     e = my_event()
-    assert find_ed_in_ast(e._ast) is e
+    assert find_ed_in_ast(e.query_ast) is e
 
 
 def test_find_event_inside():
     e = my_event()
-    add = ast.BinOp(ast.Num(5), ast.Add, e._ast)
+    add = ast.BinOp(ast.Num(5), ast.Add, e.query_ast)
     assert find_ed_in_ast(add) is e
 
 
 def test_find_event_with_more_ast():
     e = my_event_extra_args()
-    add = ast.BinOp(ast.Num(5), ast.Add, e._ast)
+    add = ast.BinOp(ast.Num(5), ast.Add, e.query_ast)
     assert find_ed_in_ast(add) is e
 
 
diff --git a/tests/test_object_stream.py b/tests/test_object_stream.py
index 9831fec..45a2140 100644
--- a/tests/test_object_stream.py
+++ b/tests/test_object_stream.py
@@ -84,6 +84,18 @@ async def test_await_exe_from_normal_function():
         .value_async()
     assert isinstance(await r, ast.AST)
 
+
+def test_ast_prop():
+    r = my_event() \
+        .SelectMany("lambda e: e.jets()") \
+        .Select("lambda j: j.pT()") \
+        .AsROOTTTree("junk.root", "analysis", "jetPT")
+
+    assert isinstance(r.query_ast, ast.AST)
+    assert isinstance(r.query_ast, ast.Call)
+
+
+
 @pytest.mark.asyncio
 async def test_2await_exe_from_coroutine():
     r1 = my_event() \

pip install -e .[complete]
parse_log_pytest
pytest
pytest pytest-asyncio pytest-cov flake8
apt-get update apt-get install -y gcc
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
astunparse==1.6.3
attrs @ file:///croot/attrs_1668696182826/work
bleach==6.0.0
certifi @ file:///croot/certifi_1671487769961/work/certifi
cffi==1.15.1
charset-normalizer==3.4.1
coverage==7.2.7
cryptography==44.0.2
docutils==0.20.1
flake8==5.0.4
flit_core @ file:///opt/conda/conda-bld/flit-core_1644941570762/work/source/flit_core
-e git+https://github.com/iris-hep/func_adl.git@b2ba083ca9e0bb70918ec0b8802eb9ce849380c7#egg=func_adl_test
idna==3.10
importlib-metadata==4.2.0
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
jaraco.classes==3.2.3
jeepney==0.9.0
keyring==23.9.3
make-it-sync==2.0.0
markdown-it-py==2.2.0
mccabe==0.7.0
mdurl==0.1.2
more-itertools==9.1.0
packaging @ file:///croot/packaging_1671697413597/work
pkginfo==1.10.0
pluggy @ file:///tmp/build/80754af9/pluggy_1648042572264/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pycodestyle==2.9.1
pycparser==2.21
pyflakes==2.5.0
Pygments==2.17.2
pytest==7.1.2
pytest-asyncio==0.21.2
pytest-cov==4.1.0
readme-renderer==37.3
requests==2.31.0
requests-toolbelt==1.0.0
rfc3986==2.0.0
rich==13.8.1
SecretStorage==3.3.3
six==1.17.0
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
twine==4.0.2
typing_extensions @ file:///croot/typing_extensions_1669924550328/work
urllib3==2.0.7
webencodings==0.5.1
zipp @ file:///croot/zipp_1672387121353/work

name: func_adl
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=22.1.0=py37h06a4308_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - flit-core=3.6.0=pyhd3eb1b0_0
  - importlib_metadata=4.11.3=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=22.0=py37h06a4308_0
  - pip=22.3.1=py37h06a4308_0
  - pluggy=1.0.0=py37h06a4308_1
  - py=1.11.0=pyhd3eb1b0_0
  - pytest=7.1.2=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py37h06a4308_0
  - typing_extensions=4.4.0=py37h06a4308_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.11.0=py37h06a4308_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - astunparse==1.6.3
      - bleach==6.0.0
      - cffi==1.15.1
      - charset-normalizer==3.4.1
      - coverage==7.2.7
      - cryptography==44.0.2
      - docutils==0.20.1
      - flake8==5.0.4
      - idna==3.10
      - importlib-metadata==4.2.0
      - jaraco-classes==3.2.3
      - jeepney==0.9.0
      - keyring==23.9.3
      - make-it-sync==2.0.0
      - markdown-it-py==2.2.0
      - mccabe==0.7.0
      - mdurl==0.1.2
      - more-itertools==9.1.0
      - pkginfo==1.10.0
      - pycodestyle==2.9.1
      - pycparser==2.21
      - pyflakes==2.5.0
      - pygments==2.17.2
      - pytest-asyncio==0.21.2
      - pytest-cov==4.1.0
      - readme-renderer==37.3
      - requests==2.31.0
      - requests-toolbelt==1.0.0
      - rfc3986==2.0.0
      - rich==13.8.1
      - secretstorage==3.3.3
      - six==1.17.0
      - twine==4.0.2
      - urllib3==2.0.7
      - webencodings==0.5.1
prefix: /opt/conda/envs/func_adl

tests/test_event_dataset.py::test_find_event_at_top tests/test_event_dataset.py::test_find_event_inside tests/test_event_dataset.py::test_find_event_with_more_ast tests/test_object_stream.py::test_ast_prop
tests/test_event_dataset.py::test_cannot_create tests/test_event_dataset.py::test_can_create tests/test_event_dataset.py::test_string_rep tests/test_object_stream.py::test_simple_query tests/test_object_stream.py::test_simple_query_parquet tests/test_object_stream.py::test_simple_query_panda tests/test_object_stream.py::test_simple_query_awkward tests/test_object_stream.py::test_nested_query_rendered_correctly tests/test_object_stream.py::test_await_exe_from_coroutine_with_throw tests/test_object_stream.py::test_await_exe_from_normal_function tests/test_object_stream.py::test_2await_exe_from_coroutine tests/test_object_stream.py::test_passed_in_executor
func_adl/object_stream.py func_adl/event_dataset.py
func_adl/object_stream.py func_adl/event_dataset.py