# Code a compute graph

## Code

Let's now try writing our own function. This assumes you have a running TinyChain host, following the instructions in [Getting Started](/guides/getting-started.md):

```python
# new file: test.py

import tinychain as tc

# this is the local TinyChain host you just started with "docker run..."
HOST = tc.host.Host("http://127.0.0.1:8702")

# this endpoint will attempt to run whatever program you send it
# without committing any write operations
ENDPOINT = "/transact/hypothetical"

# define a GET Op
# the type annotations are important!
# without them, TinyChain doesn't know what type to expect the arguments to be
@tc.get_op
def hello(name: tc.String) -> tc.String:
    return tc.String("Hello, {{name}}").render(name=name)

if __name__ == "__main__":
    cxt = tc.Context() # construct a new execution context
    cxt.hello = hello # include our function definition in the context
    cxt.result = cxt.hello("Name") # call the function

    print(HOST.post(ENDPOINT, cxt)) # evaluate the context on the host
                    
```

## Test

Check that it works as expected:

```bash
$ python3 test.py
Hello, Name         
```

This requires some scaffolding in order to set up but it's a very convenient starting point for more advanced use cases.

## Understand

If you're curious about how this works under the hood, you can inspect the JSON that gets sent to the host:

```python
# ...
tc.print_json(cxt)  
```

You should see something like:

```javascript
[
    [
        "hello",
        {
            "/state/scalar/op/get": [
                "name",
                [
                    [
                        "String_7f8cf85223d0",
                        "Hello, {{name}}"
                    ],
                    [
                        "_return",
                        {
                            "$String_7f8cf85223d0/render": {
                                "name": {
                                    "$name": []
                                }
                            }
                        }
                    ]
                ]
            ]
        }
    ],
    [
        "result",
        {
            "$hello": [
                "Name"
            ]
        }
    ]
]
                    
```

In general you shouldn't have to worry about what the generated JSON looks like, but it can be convenient to give explicit names to the internal states of an `Op`. You can do this by using the `cxt` or `txn` keyword—just like Python treats the "self" keyword specially in a method declaration, assigning it a reference to the method's instance, TinyChain treats the `cxt` or `txn` keyword specially, assigning it a reference to the `Op`'s execution context. For example:

```python
# ...
@tc.get_op
def hello(cxt, name):
    cxt.template = tc.String("Hello, {{name}}")
    return cxt.template.render(name=name)
# ...
                    
```

If you again inspect the JSON representation of your compute graph, you'll see that the anonymous "String..." name has been replaced by "template."


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tinychain.net/guides/code-a-compute-graph.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
