Calculation of multiple fields in an entity without using a calculated field

On a standard task there are the fields ‘Start Date’, ‘Due Date’ and ‘Duration’
If you change the ‘Due Date’ the ‘Duration’ updates.
If you change the ‘Duration’ the ‘Due Date’ updates.
I can see that these fields are using standard ‘Date’ and ‘Duration’ field types. Not using ‘calculated’
How can I set up these types of fields?

I know that a webhook can be used to send the event somewhere online to run code.
There is also setting up a Event Framework demon.
But is there a way to run code just within the shotgrid website? For example the webhook also runs a chunk of python instead of sending it external?

in short, no.

SG doesn’t offer any ways to modify their web app in this way, the updates you mentioned like ‘due date’ etc all happen internally server side.

I think you may have misunderstood how webhooks work, they can’t ‘run a chunk of python’ it is simply an http request sent to a url of your choosing. If you’re using AWS you can create a chalice with Lambda that basically works like a web server (i.e. receiving the webhook request and responding to it), otherwise you’d have to set up your own web server, something like a simple flask app would be enough.

Thanks Ed, good to have a definitive answer.
Thanks for the tips also.
We do have AWS. Lambda might be overkill.
I know that the docs prefer to use webhooks over an Event Framework demon.
Maybe the Event Framework demon is the better option for us though.
I also got a tip to use Zapier for the webhooks workflow

By the way Chat GPT fails miserably at this question. Really most questions about whether something is possible with an application and how to go about it. It seems to merge a whole lot of things that don’t go together and present them as fact.

1 Like

Haha, ChatGPT is funny with lots of things.

In this case you’d be better off devising your own workflow and running webhooks or even daemon to implement your own logic.

problem with chatgpt is you sort of need to already know what you’re asking for, otherwise like you said it can get easily confused with other things. FWIW I gave chatgpt a whirl and it actually did a pretty good job;


write me a simple example chalice app to deploy to aws lambda, give the full file structure for all required files. The chalice app must receive a Shotgrid webhook triggered on update of a field ‘sg_start’. It must then query Shotgrid for a field ‘sg_stop’, calculate the difference between sg_start and sg_stop, then use the result of this calculation to update another field in Shotgrid ‘sg_duration’


Sure, I can help you with that! Here is an example Chalice app that can be deployed to AWS Lambda to handle a Shotgrid webhook that updates a ‘sg_start’ field and calculates the duration based on the ‘sg_stop’ field.

To get started, you’ll need to install Chalice and create a new project. You can do this by running the following commands:

pip install chalice
chalice new-project shotgrid-webhook

This will create a new Chalice project called shotgrid-webhook with the following directory structure:

├── .chalice/
│   └── config.json
└── requirements.txt

You’ll need to update requirements.txt to include the shotgun-api3 package, which is required to interact with the Shotgrid API:


You’ll also need to update .chalice/config.json with your AWS credentials and the region where you want to deploy your Lambda function:

  "version": "2.0",
  "app_name": "shotgrid-webhook",
  "stages": {
    "dev": {
      "api_gateway_stage": "api",
      "environment_variables": {},
      "lambda_functions": {
        "webhook_handler": {
          "memory_size": 128,
          "timeout": 10,
          "environment_variables": {
            "SHOTGRID_SITE": "",
            "SHOTGRID_SCRIPT_NAME": "your-script-name",
            "SHOTGRID_SCRIPT_KEY": "your-script-key"

Replace, your-script-name, and your-script-key with the appropriate values for your Shotgrid site and API credentials.

Next, update with the following code:

from chalice import Chalice
from shotgun_api3 import Shotgun
from datetime import datetime

app = Chalice(app_name='shotgrid-webhook')

@app.route('/webhook', methods=['POST'])
def webhook_handler():
    event = app.current_request.json_body

    # Check that the webhook is triggered on an update to the 'sg_start' field
    if 'meta' not in event or 'entity_type' not in event['meta'] or 'entity_id' not in event['meta'] or 'attribute_name' not in event['meta'] or 'attribute_value' not in event['meta']:
        return {'message': 'Invalid webhook payload.'}

    if event['meta']['entity_type'] != 'Task' or event['meta']['attribute_name'] != 'sg_start':
        return {'message': 'Webhook not triggered on update to sg_start.'}

    # Connect to the Shotgrid API
    sg = Shotgun(app.current_request.environ['SHOTGRID_SITE'], app.current_request.environ['SHOTGRID_SCRIPT_NAME'], app.current_request.environ['SHOTGRID_SCRIPT_KEY'])

    # Get the Task entity
    task = sg.find_one('Task', [['id', 'is', event['meta']['entity_id']]])

    # Check that the Task entity has a 'sg_stop' field
    if 'sg_stop' not in task:
        return {'message': 'Task entity does not have an sg_stop field.'}

# Calculate the duration
start_time = datetime.strptime(task['sg_start'], '%Y-%m-%dT%H:%M:%S%z')
stop_time = datetime.strptime(task['sg_stop'], '%Y-%m-%dT%H:%M:%S%z')
duration = (stop_time - start_time).total_seconds() / 60.0

# Update the 'sg_duration' field
sg.update('Task', task['id'], {'sg_duration': duration})

return {'message': f"Duration calculated and updated to Shotgrid for Task {task['id']}: {duration} minutes."}

This code defines a webhook handler that is triggered when a Shotgrid webhook is received on the /webhook endpoint. The handler first checks that the webhook is triggered on an update to the sg_start field of a Task entity. If it is, it connects to the Shotgrid API using the credentials stored in the environment variables, retrieves the Task entity, checks that it has a sg_stop field, calculates the duration between the sg_start and sg_stop fields, and updates the sg_duration field of the Task entity with the calculated duration.

Finally, you can deploy your Chalice app to AWS Lambda by running the following command:

chalice deploy

This will deploy your app to AWS Lambda and create an API Gateway endpoint that can receive Shotgrid webhooks. You can copy the API Gateway endpoint URL from the output of the chalice deploy command and use it to create a new webhook in your Shotgrid site.

1 Like

Thanks for sharing Ed, that is pretty comprehensive.
I should have provided the response from that time. The prompt was just as it’s written here.

I just tried again. This is the response I got. Is toolkit an option? I’ll do a bit of digging when I have time.

To set up fields that update automatically based on changes to other fields, you can use the “Calculated” field type in Shotgun. However, if you prefer not to use the “Calculated” field type, you can achieve the same functionality using a custom script or tool.

One option is to use the “Toolkit” framework to create a custom tool that runs within the Shotgun website. With this approach, you can use Python code to update the “Due Date” or “Duration” fields based on changes to the other field.

Another option is to use the “Event Daemon” framework to run Python code in response to events that occur within Shotgun, such as changes to the “Start Date” or “Due Date” fields. This code can then update the “Duration” field accordingly.

Finally, as you mentioned, you can use a webhook to trigger a Python script that updates the fields. If you don’t want to send the data externally, you can use a self-hosted service, such as AWS Lambda or Google Cloud Functions, to run the Python code and then update the fields within Shotgun.

there’s no toolkit that runs on SG server side (as far as I’m aware anyway…). The closest thing I can think of that it might be (incorrectly) referring to is shotgun toolkit integrations that allow you to run local code from a right click menu option. That’s not going to help you though.

one way or another you’re going to need an external service somewhere that either responds to events, or runs periodically and updates data in SG.